106342
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
1 ;;; mpc.el --- A client for the Music Player Daemon -*- coding: utf-8 -*-
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
2
|
106815
|
3 ;; Copyright (C) 2006, 2007, 2008, 2009, 2010 Free Software Foundation, Inc.
|
106342
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
4
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
5 ;; Author: Stefan Monnier <monnier@iro.umontreal.ca>
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
6 ;; Keywords: multimedia
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
7
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
8 ;; This file is part of GNU Emacs.
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
9
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
10 ;; GNU Emacs is free software: you can redistribute it and/or modify
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
11 ;; it under the terms of the GNU General Public License as published by
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
12 ;; the Free Software Foundation, either version 3 of the License, or
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
13 ;; (at your option) any later version.
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
14
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
15 ;; GNU Emacs is distributed in the hope that it will be useful,
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
16 ;; but WITHOUT ANY WARRANTY; without even the implied warranty of
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
17 ;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
18 ;; GNU General Public License for more details.
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
19
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
20 ;; You should have received a copy of the GNU General Public License
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
21 ;; along with GNU Emacs. If not, see <http://www.gnu.org/licenses/>.
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
22
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
23 ;;; Commentary:
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
24
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
25 ;; This is an Emacs front end to the Music Player Daemon.
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
26
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
27 ;; It mostly provides a browser inspired from Rhythmbox for your music
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
28 ;; collection and also allows you to play the music you select. The basic
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
29 ;; interface is somewhat unusual in that it does not focus on the
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
30 ;; playlist as much as on the browser.
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
31 ;; I play albums rather than songs and thus don't have much need for
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
32 ;; playlists, and it shows. Playlist support exists, but is still limited.
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
33
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
34 ;; Bugs:
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
35
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
36 ;; - when reaching end/start of song while ffwd/rewind, it may get wedged,
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
37 ;; signal an error, ... or when mpc-next/prev is called while ffwd/rewind.
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
38 ;; - MPD errors are not reported to the user.
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
39
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
40 ;; Todo:
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
41
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
42 ;; - add bindings/buttons/menuentries for the various commands.
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
43 ;; - mpc-undo
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
44 ;; - visual feedback for drag'n'drop
|
106365
|
45 ;; - display/set `repeat' and `random' state (and maybe also `crossfade').
|
106342
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
46 ;; - allow multiple *mpc* sessions in the same Emacs to control different mpds.
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
47 ;; - look for .folder.png (freedesktop) or folder.jpg (XP) as well.
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
48 ;; - fetch album covers and lyrics from the web?
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
49 ;; - improve MPC-Status: better volume control, add a way to show/hide the
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
50 ;; rest, plus add the buttons currently in the toolbar.
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
51 ;; - improve mpc-songs-mode's header-line column-headings so they can be
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
52 ;; dragged to resize.
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
53 ;; - allow selecting several entries by drag-mouse.
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
54 ;; - poll less often
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
55 ;; - use the `idle' command
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
56 ;; - do the time-ticking locally (and sync every once in a while)
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
57 ;; - look at the end of play time to make sure we notice the end
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
58 ;; as soon as possible
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
59 ;; - better volume widget.
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
60 ;; - add synthesized tags.
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
61 ;; e.g. pseudo-artist = artist + composer + performer.
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
62 ;; e.g. pseudo-performer = performer or artist
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
63 ;; e.g. rewrite artist "Foo bar & baz" to "Foo bar".
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
64 ;; e.g. filename regexp -> compilation flag
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
65 ;; - window/buffer management.
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
66 ;; - menubar, tooltips, ...
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
67 ;; - add mpc-describe-song, mpc-describe-album, ...
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
68 ;; - add import/export commands (especially export to an MP3 player).
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
69 ;; - add a real notion of album (as opposed to just album-name):
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
70 ;; if all songs with same album-name have same artist -> it's an album
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
71 ;; else it's either several albums or a compilation album (or both),
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
72 ;; in which case we could use heuristics or user provided info:
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
73 ;; - if the user followed the 1-album = 1-dir idea, then we can group songs
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
74 ;; by their directory to create albums.
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
75 ;; - if a `compilation' flag is available, and if <=1 of the songs have it
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
76 ;; set, then we can group songs by their artist to create albums.
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
77 ;; - if two songs have the same track-nb and disk-nb, they're not in the
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
78 ;; same album. So from the set of songs with identical album names, we
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
79 ;; can get a lower bound on the number of albums involved, and then see
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
80 ;; which of those may be non-compilations, etc...
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
81 ;; - use a special directory name for compilations.
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
82 ;; - ask the web ;-)
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
83
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
84 ;;; Code:
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
85
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
86 ;; Prefixes used in this code:
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
87 ;; mpc-proc : management of connection (in/out formatting, ...)
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
88 ;; mpc-status : auto-updated status info
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
89 ;; mpc-volume : stuff handling the volume widget
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
90 ;; mpc-cmd : mpdlib abstraction
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
91
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
92 ;; UI-commands : mpc-
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
93 ;; internal : mpc--
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
94
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
95 (eval-when-compile (require 'cl))
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
96
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
97 ;;; Backward compatibility.
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
98 ;; This code is meant for Emacs-CVS, so to get it to run on anything else,
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
99 ;; we need to define some more things.
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
100
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
101 (unless (fboundp 'tool-bar-local-item)
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
102 (defun tool-bar-local-item (icon def key map &rest props)
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
103 (define-key-after map (vector key)
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
104 `(menu-item ,(symbol-name key) ,def
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
105 :image ,(find-image
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
106 `((:type xpm :file ,(concat icon ".xpm"))))
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
107 ,@props))))
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
108
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
109 (unless (fboundp 'process-put)
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
110 (defconst mpc-process-hash (make-hash-table :weakness 'key))
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
111 (defun process-put (proc prop val)
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
112 (let ((sym (gethash proc mpc-process-hash)))
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
113 (unless sym
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
114 (setq sym (puthash proc (make-symbol "mpc-proc-sym") mpc-process-hash)))
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
115 (put sym prop val)))
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
116 (defun process-get (proc prop)
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
117 (let ((sym (gethash proc mpc-process-hash)))
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
118 (when sym (get sym prop))))
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
119 (defun process-plist (proc)
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
120 (let ((sym (gethash proc mpc-process-hash)))
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
121 (when sym (symbol-plist sym)))))
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
122 (unless (fboundp 'with-local-quit)
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
123 (defmacro with-local-quit (&rest body)
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
124 `(condition-case nil (let ((inhibit-quit nil)) ,@body)
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
125 (quit (setq quit-flag t) nil))))
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
126 (unless (fboundp 'balance-windows-area)
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
127 (defalias 'balance-windows-area 'balance-windows))
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
128 (unless (fboundp 'posn-object) (defalias 'posn-object 'ignore))
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
129 (unless (fboundp 'buffer-local-value)
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
130 (defun buffer-local-value (var buf)
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
131 (with-current-buffer buf (symbol-value var))))
|
106354
|
132
|
106342
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
133
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
134 ;;; Main code starts here.
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
135
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
136 (defgroup mpc ()
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
137 "A Client for the Music Player Daemon."
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
138 :prefix "mpc-"
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
139 :group 'multimedia
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
140 :group 'applications)
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
141
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
142 (defcustom mpc-browser-tags '(Genre Artist Album Playlist)
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
143 "Tags for which a browser buffer should be created by default."
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
144 :type '(repeat string))
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
145
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
146 ;;; Misc utils ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
147
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
148 (defun mpc-assq-all (key alist)
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
149 (let ((res ()) val)
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
150 (dolist (elem alist)
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
151 (if (and (eq (car elem) key)
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
152 (not (member (setq val (cdr elem)) res)))
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
153 (push val res)))
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
154 (nreverse res)))
|
106354
|
155
|
106342
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
156 (defun mpc-union (&rest lists)
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
157 (let ((res (nreverse (pop lists))))
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
158 (dolist (list lists)
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
159 (let ((seen res)) ;Don't remove duplicates within each list.
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
160 (dolist (elem list)
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
161 (unless (member elem seen) (push elem res)))))
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
162 (nreverse res)))
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
163
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
164 (defun mpc-intersection (l1 l2 &optional selectfun)
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
165 "Return L1 after removing all elements not found in L2.
|
106365
|
166 If SELECTFUN is non-nil, elements aren't compared directly, but instead
|
|
167 they are passed through SELECTFUN before comparison."
|
106342
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
168 (let ((res ()))
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
169 (if selectfun (setq l2 (mapcar selectfun l2)))
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
170 (dolist (elem l1)
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
171 (when (member (if selectfun (funcall selectfun elem) elem) l2)
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
172 (push elem res)))
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
173 (nreverse res)))
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
174
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
175 (defun mpc-event-set-point (event)
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
176 (condition-case nil (posn-set-point (event-end event))
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
177 (error (condition-case nil (mouse-set-point event)
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
178 (error nil)))))
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
179
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
180 (defun mpc-compare-strings (str1 str2 &optional ignore-case)
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
181 "Compare strings STR1 and STR2.
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
182 Contrary to `compare-strings', this tries to get numbers sorted
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
183 numerically rather than lexicographically."
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
184 (let ((res (compare-strings str1 nil nil str2 nil nil ignore-case)))
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
185 (if (not (integerp res)) res
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
186 (let ((index (1- (abs res))))
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
187 (if (or (>= index (length str1)) (>= index (length str2)))
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
188 res
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
189 (let ((digit1 (memq (aref str1 index)
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
190 '(?0 ?1 ?2 ?3 ?4 ?5 ?6 ?7 ?8 ?9)))
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
191 (digit2 (memq (aref str2 index)
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
192 '(?0 ?1 ?2 ?3 ?4 ?5 ?6 ?7 ?8 ?9))))
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
193 (if digit1
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
194 (if digit2
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
195 (let ((num1 (progn (string-match "[0-9]+" str1 index)
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
196 (match-string 0 str1)))
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
197 (num2 (progn (string-match "[0-9]+" str2 index)
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
198 (match-string 0 str2))))
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
199 (cond
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
200 ;; Here we presume that leading zeroes are only used
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
201 ;; for same-length numbers. So we'll incorrectly
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
202 ;; consider that "000" comes after "01", but I don't
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
203 ;; think it matters.
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
204 ((< (length num1) (length num2)) (- (abs res)))
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
205 ((> (length num1) (length num2)) (abs res))
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
206 ((< (string-to-number num1) (string-to-number num2))
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
207 (- (abs res)))
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
208 (t (abs res))))
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
209 ;; "1a" comes before "10", but "0" comes before "a".
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
210 (if (and (not (zerop index))
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
211 (memq (aref str1 (1- index))
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
212 '(?0 ?1 ?2 ?3 ?4 ?5 ?6 ?7 ?8 ?9)))
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
213 (abs res)
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
214 (- (abs res))))
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
215 (if digit2
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
216 ;; "1a" comes before "10", but "0" comes before "a".
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
217 (if (and (not (zerop index))
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
218 (memq (aref str1 (1- index))
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
219 '(?0 ?1 ?2 ?3 ?4 ?5 ?6 ?7 ?8 ?9)))
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
220 (- (abs res))
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
221 (abs res))
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
222 res))))))))
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
223
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
224 (defun mpc-string-prefix-p (str1 str2)
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
225 ;; FIXME: copied from pcvs-util.el.
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
226 "Tell whether STR1 is a prefix of STR2."
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
227 (eq t (compare-strings str2 nil (length str1) str1 nil nil)))
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
228
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
229 ;; This can speed up mpc--song-search significantly. The table may grow
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
230 ;; very large, tho. It's only bounded by the fact that it gets flushed
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
231 ;; whenever the connection is established; which seems to work OK thanks
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
232 ;; to the fact that MPD tends to disconnect fairly often, although our
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
233 ;; constant polling often prevents disconnection.
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
234 (defvar mpc--find-memoize (make-hash-table :test 'equal)) ;; :weakness t
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
235 (defvar mpc-tag nil) (make-variable-buffer-local 'mpc-tag)
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
236
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
237 ;;; Support for the actual connection and MPD command execution ;;;;;;;;;;;;
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
238
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
239 (defcustom mpc-host
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
240 (concat (or (getenv "MPD_HOST") "localhost")
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
241 (if (getenv "MPD_PORT") (concat ":" (getenv "MPD_PORT"))))
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
242 "Host (and port) where the Music Player Daemon is running.
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
243 The format is \"HOST\" or \"HOST:PORT\" where PORT defaults to 6600
|
106365
|
244 and HOST defaults to localhost."
|
106342
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
245 :type 'string)
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
246
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
247 (defvar mpc-proc nil)
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
248
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
249 (defconst mpc--proc-end-re "^\\(?:OK\\(?: MPD .*\\)?\\|ACK \\(.*\\)\\)\n")
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
250
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
251 (put 'mpc-proc-error 'error-conditions '(mpc-proc-error error))
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
252 (put 'mpc-proc-error 'error-message "MPD error")
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
253
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
254 (defun mpc--debug (format &rest args)
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
255 (if (get-buffer "*MPC-debug*")
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
256 (with-current-buffer "*MPC-debug*"
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
257 (goto-char (point-max))
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
258 (insert-before-markers ;So it scrolls.
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
259 (replace-regexp-in-string "\n" "\n "
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
260 (apply 'format format args))
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
261 "\n"))))
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
262
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
263 (defun mpc--proc-filter (proc string)
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
264 (mpc--debug "Receive \"%s\"" string)
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
265 (with-current-buffer (process-buffer proc)
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
266 (if (process-get proc 'ready)
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
267 (if nil ;; (string-match "\\`\\(OK\n\\)+\\'" string)
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
268 ;; I haven't figured out yet why I get those extraneous OKs,
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
269 ;; so I'll just ignore them for now.
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
270 nil
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
271 (delete-process proc)
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
272 (set-process-buffer proc nil)
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
273 (pop-to-buffer (clone-buffer))
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
274 (error "MPD output while idle!?"))
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
275 (save-excursion
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
276 (let ((start (or (marker-position (process-mark proc)) (point-min))))
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
277 (goto-char start)
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
278 (insert string)
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
279 (move-marker (process-mark proc) (point))
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
280 (beginning-of-line)
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
281 (when (and (< start (point))
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
282 (re-search-backward mpc--proc-end-re start t))
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
283 (process-put proc 'ready t)
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
284 (unless (eq (match-end 0) (point-max))
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
285 (error "Unexpected trailing text"))
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
286 (let ((error (match-string 1)))
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
287 (delete-region (point) (point-max))
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
288 (let ((callback (process-get proc 'callback)))
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
289 (process-put proc 'callback nil)
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
290 (if error (signal 'mpc-proc-error error))
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
291 (funcall callback)))))))))
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
292
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
293 (defun mpc--proc-connect (host)
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
294 (mpc--debug "Connecting to %s..." host)
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
295 (with-current-buffer (get-buffer-create (format " *mpc-%s*" host))
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
296 ;; (pop-to-buffer (current-buffer))
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
297 (let (proc)
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
298 (while (and (setq proc (get-buffer-process (current-buffer)))
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
299 (progn ;; (debug)
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
300 (delete-process proc)))))
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
301 (erase-buffer)
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
302 (let ((port 6600))
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
303 (when (string-match ":[^.]+\\'" host)
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
304 (setq port (substring host (1+ (match-beginning 0))))
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
305 (setq host (substring host 0 (match-beginning 0)))
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
306 (unless (string-match "[^[:digit:]]" port)
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
307 (setq port (string-to-number port))))
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
308 (let* ((coding-system-for-read 'utf-8-unix)
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
309 (coding-system-for-write 'utf-8-unix)
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
310 (proc (open-network-stream "MPC" (current-buffer) host port)))
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
311 (when (processp mpc-proc)
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
312 ;; Inherit the properties of the previous connection.
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
313 (let ((plist (process-plist mpc-proc)))
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
314 (while plist (process-put proc (pop plist) (pop plist)))))
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
315 (mpc-proc-buffer proc 'mpd-commands (current-buffer))
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
316 (process-put proc 'callback 'ignore)
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
317 (process-put proc 'ready nil)
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
318 (clrhash mpc--find-memoize)
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
319 (set-process-filter proc 'mpc--proc-filter)
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
320 (set-process-sentinel proc 'ignore)
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
321 (set-process-query-on-exit-flag proc nil)
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
322 ;; This may be called within a process filter ;-(
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
323 (with-local-quit (mpc-proc-sync proc))
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
324 proc))))
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
325
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
326 (defun mpc--proc-quote-string (s)
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
327 (if (numberp s) (number-to-string s)
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
328 (setq s (replace-regexp-in-string "[\"\\]" "\\\\\\&" s))
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
329 (if (string-match " " s) (concat "\"" s "\"") s)))
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
330
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
331 (defconst mpc--proc-alist-to-alists-starters '(file directory))
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
332
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
333 (defun mpc--proc-alist-to-alists (alist)
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
334 (assert (or (null alist)
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
335 (memq (caar alist) mpc--proc-alist-to-alists-starters)))
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
336 (let ((starter (caar alist))
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
337 (alists ())
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
338 tmp)
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
339 (dolist (pair alist)
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
340 (when (eq (car pair) starter)
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
341 (if tmp (push (nreverse tmp) alists))
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
342 (setq tmp ()))
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
343 (push pair tmp))
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
344 (if tmp (push (nreverse tmp) alists))
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
345 (nreverse alists)))
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
346
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
347 (defun mpc-proc ()
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
348 (or (and mpc-proc
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
349 (buffer-live-p (process-buffer mpc-proc))
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
350 (not (memq (process-status mpc-proc) '(closed)))
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
351 mpc-proc)
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
352 (setq mpc-proc (mpc--proc-connect mpc-host))))
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
353
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
354 (defun mpc-proc-sync (&optional proc)
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
355 "Wait for MPC process until it is idle again.
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
356 Return the buffer in which the process is/was running."
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
357 (unless proc (setq proc (mpc-proc)))
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
358 (unwind-protect
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
359 (condition-case err
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
360 (progn
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
361 (while (and (not (process-get proc 'ready))
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
362 (accept-process-output proc)))
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
363 (if (process-get proc 'ready) (process-buffer proc)
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
364 ;; (delete-process proc)
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
365 (error "No response from MPD")))
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
366 (error (message "MPC: %s" err) (signal (car err) (cdr err))))
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
367 (unless (process-get proc 'ready)
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
368 ;; (debug)
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
369 (message "Killing hung process")
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
370 (delete-process proc))))
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
371
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
372 (defun mpc-proc-cmd (cmd &optional callback)
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
373 "Send command CMD to the MPD server.
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
374 If CALLBACK is nil, wait for the command to finish before returning,
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
375 otherwise return immediately and call CALLBACK with no argument
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
376 when the command terminates.
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
377 CMD can be a string which is passed as-is to MPD or a list of strings
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
378 which will be concatenated with proper quoting before passing them to MPD."
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
379 (let ((proc (mpc-proc)))
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
380 (if (and callback (not (process-get proc 'ready)))
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
381 (lexical-let ((old (process-get proc 'callback))
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
382 (callback callback)
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
383 (cmd cmd))
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
384 (process-put proc 'callback
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
385 (lambda ()
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
386 (funcall old)
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
387 (mpc-proc-cmd cmd callback))))
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
388 ;; Wait for any pending async command to terminate.
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
389 (mpc-proc-sync proc)
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
390 (process-put proc 'ready nil)
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
391 (with-current-buffer (process-buffer proc)
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
392 (erase-buffer)
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
393 (mpc--debug "Send \"%s\"" cmd)
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
394 (process-send-string
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
395 proc (concat (if (stringp cmd) cmd
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
396 (mapconcat 'mpc--proc-quote-string cmd " "))
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
397 "\n")))
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
398 (if callback
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
399 (lexical-let ((buf (current-buffer))
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
400 (callback callback))
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
401 (process-put proc 'callback
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
402 callback
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
403 ;; (lambda ()
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
404 ;; (funcall callback
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
405 ;; (prog1 (current-buffer)
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
406 ;; (set-buffer buf))))
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
407 ))
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
408 ;; If `callback' is nil, we're executing synchronously.
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
409 (process-put proc 'callback 'ignore)
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
410 ;; This returns the process's buffer.
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
411 (mpc-proc-sync proc)))))
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
412
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
413 ;; This function doesn't exist in Emacs-21.
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
414 ;; (put 'mpc-proc-cmd-list 'byte-optimizer 'byte-optimize-pure-func)
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
415 (defun mpc-proc-cmd-list (cmds)
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
416 (concat "command_list_begin\n"
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
417 (mapconcat (lambda (cmd)
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
418 (if (stringp cmd) cmd
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
419 (mapconcat 'mpc--proc-quote-string cmd " ")))
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
420 cmds
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
421 "\n")
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
422 "\ncommand_list_end"))
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
423
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
424 (defun mpc-proc-cmd-list-ok ()
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
425 ;; To implement this, we'll need to tweak the process filter since we'd
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
426 ;; then sometimes get "trailing" text after "OK\n".
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
427 (error "Not implemented yet"))
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
428
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
429 (defun mpc-proc-buf-to-alist (&optional buf)
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
430 (with-current-buffer (or buf (current-buffer))
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
431 (let ((res ()))
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
432 (goto-char (point-min))
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
433 (while (re-search-forward "^\\([^:]+\\): \\(.*\\)\n" nil t)
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
434 (push (cons (intern (match-string 1)) (match-string 2)) res))
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
435 (nreverse res))))
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
436
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
437 (defun mpc-proc-buf-to-alists (buf)
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
438 (mpc--proc-alist-to-alists (mpc-proc-buf-to-alist buf)))
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
439
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
440 (defun mpc-proc-cmd-to-alist (cmd &optional callback)
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
441 (if callback
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
442 (lexical-let ((buf (current-buffer))
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
443 (callback callback))
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
444 (mpc-proc-cmd cmd (lambda ()
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
445 (funcall callback (prog1 (mpc-proc-buf-to-alist
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
446 (current-buffer))
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
447 (set-buffer buf))))))
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
448 ;; (lexical-let ((res nil))
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
449 ;; (mpc-proc-cmd-to-alist cmd (lambda (alist) (setq res alist)))
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
450 ;; (mpc-proc-sync)
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
451 ;; res)
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
452 (mpc-proc-buf-to-alist (mpc-proc-cmd cmd))))
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
453
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
454 (defun mpc-proc-tag-string-to-sym (tag)
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
455 (intern (capitalize tag)))
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
456
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
457 (defun mpc-proc-buffer (proc use &optional buffer)
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
458 (let* ((bufs (process-get proc 'buffers))
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
459 (buf (cdr (assoc use bufs))))
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
460 (cond
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
461 ((and buffer (buffer-live-p buf) (not (eq buffer buf)))
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
462 (error "Duplicate MPC buffer for %s" use))
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
463 (buffer
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
464 (if buf
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
465 (setcdr (assoc use bufs) buffer)
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
466 (process-put proc 'buffers (cons (cons use buffer) bufs))))
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
467 (t buf))))
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
468
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
469 ;;; Support for regularly updated current status information ;;;;;;;;;;;;;;;
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
470
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
471 ;; Exported elements:
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
472 ;; `mpc-status' holds the uptodate data.
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
473 ;; `mpc-status-callbacks' holds the registered callback functions.
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
474 ;; `mpc-status-refresh' forces a refresh of the data.
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
475 ;; `mpc-status-stop' stops the automatic updating.
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
476
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
477 (defvar mpc-status nil)
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
478 (defvar mpc-status-callbacks
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
479 '((state . mpc--status-timers-refresh)
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
480 ;; (song . mpc--queue-refresh)
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
481 ;; (state . mpc--queue-refresh) ;To detect the end of the last song.
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
482 (state . mpc--faster-toggle-refresh) ;Only ffwd/rewind while play/pause.
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
483 (volume . mpc-volume-refresh)
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
484 (file . mpc-songpointer-refresh)
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
485 ;; The song pointer may need updating even if the file doesn't change,
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
486 ;; if the same song appears multiple times in a row.
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
487 (song . mpc-songpointer-refresh)
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
488 (updating_db . mpc-updated-db)
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
489 (updating_db . mpc--status-timers-refresh)
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
490 (t . mpc-current-refresh))
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
491 "Alist associating properties to the functions that care about them.
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
492 Each entry has the form (PROP . FUN) where PROP can be t to mean
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
493 to call FUN for any change whatsoever.")
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
494
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
495 (defun mpc--status-callback ()
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
496 (let ((old-status mpc-status))
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
497 ;; Update the alist.
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
498 (setq mpc-status (mpc-proc-buf-to-alist))
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
499 (assert mpc-status)
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
500 (unless (equal old-status mpc-status)
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
501 ;; Run the relevant refresher functions.
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
502 (dolist (pair mpc-status-callbacks)
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
503 (when (or (eq t (car pair))
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
504 (not (equal (cdr (assq (car pair) old-status))
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
505 (cdr (assq (car pair) mpc-status)))))
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
506 (funcall (cdr pair)))))))
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
507
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
508 (defvar mpc--status-timer nil)
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
509 (defun mpc--status-timer-start ()
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
510 (add-hook 'pre-command-hook 'mpc--status-timer-stop)
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
511 (unless mpc--status-timer
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
512 (setq mpc--status-timer (run-with-timer 1 1 'mpc--status-timer-run))))
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
513 (defun mpc--status-timer-stop ()
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
514 (when mpc--status-timer
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
515 (cancel-timer mpc--status-timer)
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
516 (setq mpc--status-timer nil)))
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
517 (defun mpc--status-timer-run ()
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
518 (when (process-get (mpc-proc) 'ready)
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
519 (condition-case err
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
520 (with-local-quit (mpc-status-refresh))
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
521 (error (message "MPC: %s" err)))))
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
522
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
523 (defvar mpc--status-idle-timer nil)
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
524 (defun mpc--status-idle-timer-start ()
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
525 (when mpc--status-idle-timer
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
526 ;; Turn it off even if we'll start it again, in case it changes the delay.
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
527 (cancel-timer mpc--status-idle-timer))
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
528 (setq mpc--status-idle-timer
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
529 (run-with-idle-timer 1 t 'mpc--status-idle-timer-run))
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
530 ;; Typically, the idle timer is started from the mpc--status-callback,
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
531 ;; which is run asynchronously while we're already idle (we typically
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
532 ;; just started idling), so the timer itself will only be run the next
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
533 ;; time we idle :-(
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
534 ;; To work around that, we immediately start the repeat timer.
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
535 (mpc--status-timer-start))
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
536 (defun mpc--status-idle-timer-stop (&optional really)
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
537 (when mpc--status-idle-timer
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
538 ;; Turn it off even if we'll start it again, in case it changes the delay.
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
539 (cancel-timer mpc--status-idle-timer))
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
540 (setq mpc--status-idle-timer
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
541 (unless really
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
542 ;; We don't completely stop the timer, so that if some other MPD
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
543 ;; client starts playback, we may get a chance to notice it.
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
544 (run-with-idle-timer 10 t 'mpc--status-idle-timer-run))))
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
545 (defun mpc--status-idle-timer-run ()
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
546 (when (process-get (mpc-proc) 'ready)
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
547 (condition-case err
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
548 (with-local-quit (mpc-status-refresh))
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
549 (error (message "MPC: %s" err))))
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
550 (mpc--status-timer-start))
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
551
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
552 (defun mpc--status-timers-refresh ()
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
553 "Start/stop the timers according to whether a song is playing."
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
554 (if (or (member (cdr (assq 'state mpc-status)) '("play"))
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
555 (cdr (assq 'updating_db mpc-status)))
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
556 (mpc--status-idle-timer-start)
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
557 (mpc--status-idle-timer-stop)
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
558 (mpc--status-timer-stop)))
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
559
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
560 (defun mpc-status-refresh (&optional callback)
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
561 "Refresh `mpc-status'."
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
562 (lexical-let ((cb callback))
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
563 (mpc-proc-cmd (mpc-proc-cmd-list '("status" "currentsong"))
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
564 (lambda ()
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
565 (mpc--status-callback)
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
566 (if cb (funcall cb))))))
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
567
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
568 (defun mpc-status-stop ()
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
569 "Stop the autorefresh of `mpc-status'.
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
570 This is normally used only when quitting MPC.
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
571 Any call to `mpc-status-refresh' may cause it to be restarted."
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
572 (setq mpc-status nil)
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
573 (mpc--status-idle-timer-stop 'really)
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
574 (mpc--status-timer-stop))
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
575
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
576 ;;; A thin layer above the raw protocol commands ;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
577
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
578 ;; (defvar mpc-queue nil)
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
579 ;; (defvar mpc-queue-back nil)
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
580
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
581 ;; (defun mpc--queue-head ()
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
582 ;; (if (stringp (car mpc-queue)) (car mpc-queue) (cadar mpc-queue)))
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
583 ;; (defun mpc--queue-pop ()
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
584 ;; (when mpc-queue ;Can be nil if out of sync.
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
585 ;; (let ((song (car mpc-queue)))
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
586 ;; (assert song)
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
587 ;; (push (if (and (consp song) (cddr song))
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
588 ;; ;; The queue's first element is itself a list of
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
589 ;; ;; songs, where the first element isn't itself a song
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
590 ;; ;; but a description of the list.
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
591 ;; (prog1 (cadr song) (setcdr song (cddr song)))
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
592 ;; (prog1 (if (consp song) (cadr song) song)
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
593 ;; (setq mpc-queue (cdr mpc-queue))))
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
594 ;; mpc-queue-back)
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
595 ;; (assert (stringp (car mpc-queue-back))))))
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
596
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
597 ;; (defun mpc--queue-refresh ()
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
598 ;; ;; Maintain the queue.
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
599 ;; (mpc--debug "mpc--queue-refresh")
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
600 ;; (let ((pos (cdr (or (assq 'Pos mpc-status) (assq 'song mpc-status)))))
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
601 ;; (cond
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
602 ;; ((null pos)
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
603 ;; (mpc-cmd-clear 'ignore))
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
604 ;; ((or (not (member pos '("0" nil)))
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
605 ;; ;; There's only one song in the playlist and we've stopped.
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
606 ;; ;; Maybe it's because of some external client that set the
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
607 ;; ;; playlist like that and/or manually stopped the playback, but
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
608 ;; ;; it's more likely that we've simply reached the end of
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
609 ;; ;; the song. So remove it.
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
610 ;; (and (equal (assq 'state mpc-status) "stop")
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
611 ;; (equal (assq 'playlistlength mpc-status) "1")
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
612 ;; (setq pos "1")))
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
613 ;; ;; We're not playing the first song in the queue/playlist any
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
614 ;; ;; more, so update the queue.
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
615 ;; (dotimes (i (string-to-number pos)) (mpc--queue-pop))
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
616 ;; (mpc-proc-cmd (mpc-proc-cmd-list
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
617 ;; (make-list (string-to-number pos) "delete 0"))
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
618 ;; 'ignore)
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
619 ;; (if (not (equal (cdr (assq 'file mpc-status))
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
620 ;; (mpc--queue-head)))
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
621 ;; (message "MPC's queue is out of sync"))))))
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
622
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
623 (defun mpc-cmd-find (tag value)
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
624 "Return a list of all songs whose tag TAG has value VALUE.
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
625 The songs are returned as alists."
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
626 (or (gethash (cons tag value) mpc--find-memoize)
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
627 (puthash (cons tag value)
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
628 (cond
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
629 ((eq tag 'Playlist)
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
630 ;; Special case for pseudo-tag playlist.
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
631 (let ((l (mpc-proc-buf-to-alists
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
632 (mpc-proc-cmd (list "listplaylistinfo" value))))
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
633 (i 0))
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
634 (mapcar (lambda (s)
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
635 (prog1 (cons (cons 'Pos (number-to-string i)) s)
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
636 (incf i)))
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
637 l)))
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
638 ((eq tag 'Search)
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
639 (mpc-proc-buf-to-alists
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
640 (mpc-proc-cmd (list "search" "any" value))))
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
641 ((eq tag 'Directory)
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
642 (let ((pairs
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
643 (mpc-proc-buf-to-alist
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
644 (mpc-proc-cmd (list "listallinfo" value)))))
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
645 (mpc--proc-alist-to-alists
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
646 ;; Strip away the `directory' entries.
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
647 (delq nil (mapcar (lambda (pair)
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
648 (if (eq (car pair) 'directory)
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
649 nil pair))
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
650 pairs)))))
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
651 (t
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
652 (condition-case err
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
653 (mpc-proc-buf-to-alists
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
654 (mpc-proc-cmd (list "find" (symbol-name tag) value)))
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
655 (mpc-proc-error
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
656 ;; If `tag' is not one of the expected tags, MPD burps
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
657 ;; about not having the relevant table. FIXME: check
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
658 ;; the kind of error.
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
659 (error "Unknown tag %s" tag)
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
660 (let ((res ()))
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
661 (setq value (cons tag value))
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
662 (dolist (song (mpc-proc-buf-to-alists
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
663 (mpc-proc-cmd "listallinfo")))
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
664 (if (member value song) (push song res)))
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
665 res)))))
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
666 mpc--find-memoize)))
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
667
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
668 (defun mpc-cmd-list (tag &optional other-tag value)
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
669 ;; FIXME: we could also provide a `mpc-cmd-list' alternative which
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
670 ;; doesn't take an "other-tag value" constraint but a "song-list" instead.
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
671 ;; That might be more efficient in some cases.
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
672 (cond
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
673 ((eq tag 'Playlist)
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
674 (let ((pls (mpc-assq-all 'playlist (mpc-proc-cmd-to-alist "lsinfo"))))
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
675 (when other-tag
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
676 (dolist (pl (prog1 pls (setq pls nil)))
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
677 (let ((plsongs (mpc-cmd-find 'Playlist pl)))
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
678 (if (not (member other-tag '(Playlist Search Directory)))
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
679 (when (member (cons other-tag value)
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
680 (apply 'append plsongs))
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
681 (push pl pls))
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
682 ;; Problem N°2: we compute the intersection whereas all
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
683 ;; we care about is whether it's empty. So we could
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
684 ;; speed this up significantly.
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
685 ;; We only compare file names, because the full song-entries
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
686 ;; are slightly different (the ones in plsongs include
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
687 ;; position and id info specific to the playlist), and it's
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
688 ;; good enough because this is only used with "search", which
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
689 ;; doesn't pay attention to playlists and URLs anyway.
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
690 (let* ((osongs (mpc-cmd-find other-tag value))
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
691 (ofiles (mpc-assq-all 'file (apply 'append osongs)))
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
692 (plfiles (mpc-assq-all 'file (apply 'append plsongs))))
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
693 (when (mpc-intersection plfiles ofiles)
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
694 (push pl pls)))))))
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
695 pls))
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
696
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
697 ((eq tag 'Directory)
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
698 (if (null other-tag)
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
699 (apply 'nconc
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
700 (mpc-assq-all 'directory
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
701 (mpc-proc-buf-to-alist
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
702 (mpc-proc-cmd "lsinfo")))
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
703 (mapcar (lambda (dir)
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
704 (let ((shortdir
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
705 (if (get-text-property 0 'display dir)
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
706 (concat " "
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
707 (get-text-property 0 'display dir))
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
708 " ↪ "))
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
709 (subdirs
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
710 (mpc-assq-all 'directory
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
711 (mpc-proc-buf-to-alist
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
712 (mpc-proc-cmd (list "lsinfo" dir))))))
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
713 (dolist (subdir subdirs)
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
714 (put-text-property 0 (1+ (length dir))
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
715 'display shortdir
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
716 subdir))
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
717 subdirs))
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
718 (process-get (mpc-proc) 'Directory)))
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
719 ;; If there's an other-tag, then just extract the dir info from the
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
720 ;; list of other-tag's songs.
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
721 (let* ((other-songs (mpc-cmd-find other-tag value))
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
722 (files (mpc-assq-all 'file (apply 'append other-songs)))
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
723 (dirs '()))
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
724 (dolist (file files)
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
725 (let ((dir (file-name-directory file)))
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
726 (if (and dir (setq dir (directory-file-name dir))
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
727 (not (equal dir (car dirs))))
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
728 (push dir dirs))))
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
729 ;; Dirs might have duplicates still.
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
730 (setq dirs (delete-dups dirs))
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
731 (let ((newdirs dirs))
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
732 (while newdirs
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
733 (let ((dir (file-name-directory (pop newdirs))))
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
734 (when (and dir (setq dir (directory-file-name dir))
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
735 (not (member dir dirs)))
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
736 (push dir newdirs)
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
737 (push dir dirs)))))
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
738 dirs)))
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
739
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
740 ;; The UI should not provide access to such a thing anyway currently.
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
741 ;; But I could imagine adding in the future a browser for the "search"
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
742 ;; tag, which would provide things like previous searches. Not sure how
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
743 ;; useful that would be tho.
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
744 ((eq tag 'Search) (error "Not supported"))
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
745
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
746 ((null other-tag)
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
747 (condition-case nil
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
748 (mapcar 'cdr (mpc-proc-cmd-to-alist (list "list" (symbol-name tag))))
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
749 (mpc-proc-error
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
750 ;; If `tag' is not one of the expected tags, MPD burps about not
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
751 ;; having the relevant table.
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
752 ;; FIXME: check the kind of error.
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
753 (error "MPD does not know this tag %s" tag)
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
754 (mpc-assq-all tag (mpc-proc-cmd-to-alist "listallinfo")))))
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
755 (t
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
756 (condition-case nil
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
757 (if (member other-tag '(Search Playlist Directory))
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
758 (signal 'mpc-proc-error "Not implemented")
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
759 (mapcar 'cdr
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
760 (mpc-proc-cmd-to-alist
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
761 (list "list" (symbol-name tag)
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
762 (symbol-name other-tag) value))))
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
763 (mpc-proc-error
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
764 ;; DAMN!! the 3-arg form of `list' is new in 0.12 !!
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
765 ;; FIXME: check the kind of error.
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
766 (let ((other-songs (mpc-cmd-find other-tag value)))
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
767 (mpc-assq-all tag
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
768 ;; Don't use `nconc' now that mpc-cmd-find may
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
769 ;; return a memoized result.
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
770 (apply 'append other-songs))))))))
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
771
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
772 (defun mpc-cmd-stop (&optional callback)
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
773 (mpc-proc-cmd "stop" callback))
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
774
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
775 (defun mpc-cmd-clear (&optional callback)
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
776 (mpc-proc-cmd "clear" callback)
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
777 ;; (setq mpc-queue-back nil mpc-queue nil)
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
778 )
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
779
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
780 (defun mpc-cmd-pause (&optional arg callback)
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
781 "Pause or resume playback of the queue of songs."
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
782 (lexical-let ((cb callback))
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
783 (mpc-proc-cmd (list "pause" arg)
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
784 (lambda () (mpc-status-refresh) (if cb (funcall cb))))
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
785 (unless callback (mpc-proc-sync))))
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
786
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
787 (defun mpc-cmd-status ()
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
788 (mpc-proc-cmd-to-alist "status"))
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
789
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
790 (defun mpc-cmd-play ()
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
791 (mpc-proc-cmd "play")
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
792 (mpc-status-refresh))
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
793
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
794 (defun mpc-cmd-add (files &optional playlist)
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
795 "Add the songs FILES to PLAYLIST.
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
796 If PLAYLIST is t or nil or missing, use the main playlist."
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
797 (mpc-proc-cmd (mpc-proc-cmd-list
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
798 (mapcar (lambda (file)
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
799 (if (stringp playlist)
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
800 (list "playlistadd" playlist file)
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
801 (list "add" file)))
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
802 files)))
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
803 (if (stringp playlist)
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
804 (puthash (cons 'Playlist playlist) nil mpc--find-memoize)))
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
805
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
806 (defun mpc-cmd-delete (song-poss &optional playlist)
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
807 "Delete the songs at positions SONG-POSS from PLAYLIST.
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
808 If PLAYLIST is t or nil or missing, use the main playlist."
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
809 (mpc-proc-cmd (mpc-proc-cmd-list
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
810 (mapcar (lambda (song-pos)
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
811 (if (stringp playlist)
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
812 (list "playlistdelete" playlist song-pos)
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
813 (list "delete" song-pos)))
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
814 ;; Sort them from last to first, so the renumbering
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
815 ;; caused by the earlier deletions don't affect
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
816 ;; later ones.
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
817 (sort song-poss '>))))
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
818 (if (stringp playlist)
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
819 (puthash (cons 'Playlist playlist) nil mpc--find-memoize)))
|
106354
|
820
|
106342
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
821
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
822 (defun mpc-cmd-move (song-poss dest-pos &optional playlist)
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
823 (let ((i 0))
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
824 (mpc-proc-cmd
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
825 (mpc-proc-cmd-list
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
826 (mapcar (lambda (song-pos)
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
827 (if (>= song-pos dest-pos)
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
828 ;; positions past dest-pos have been
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
829 ;; shifted by i.
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
830 (setq song-pos (+ song-pos i)))
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
831 (prog1 (if (stringp playlist)
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
832 (list "playlistmove" playlist song-pos dest-pos)
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
833 (list "move" song-pos dest-pos))
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
834 (if (< song-pos dest-pos)
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
835 ;; This move has shifted dest-pos by 1.
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
836 (decf dest-pos))
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
837 (incf i)))
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
838 ;; Sort them from last to first, so the renumbering
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
839 ;; caused by the earlier deletions affect
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
840 ;; later ones a bit less.
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
841 (sort song-poss '>))))
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
842 (if (stringp playlist)
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
843 (puthash (cons 'Playlist playlist) nil mpc--find-memoize))))
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
844
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
845 (defun mpc-cmd-update (&optional arg callback)
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
846 (lexical-let ((cb callback))
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
847 (mpc-proc-cmd (if arg (list "update" arg) "update")
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
848 (lambda () (mpc-status-refresh) (if cb (funcall cb))))
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
849 (unless callback (mpc-proc-sync))))
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
850
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
851 (defun mpc-cmd-tagtypes ()
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
852 (mapcar 'cdr (mpc-proc-cmd-to-alist "tagtypes")))
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
853
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
854 ;; This was never integrated into MPD.
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
855 ;; (defun mpc-cmd-download (file)
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
856 ;; (with-current-buffer (generate-new-buffer " *mpc download*")
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
857 ;; (set-buffer-multibyte nil)
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
858 ;; (let* ((proc (mpc-proc))
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
859 ;; (stdbuf (process-buffer proc))
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
860 ;; (markpos (marker-position (process-mark proc)))
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
861 ;; (stdcoding (process-coding-system proc)))
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
862 ;; (unwind-protect
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
863 ;; (progn
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
864 ;; (set-process-buffer proc (current-buffer))
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
865 ;; (set-process-coding-system proc 'binary (cdr stdcoding))
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
866 ;; (set-marker (process-mark proc) (point))
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
867 ;; (mpc-proc-cmd (list "download" file)))
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
868 ;; (set-process-buffer proc stdbuf)
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
869 ;; (set-marker (process-mark proc) markpos stdbuf)
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
870 ;; (set-process-coding-system proc (car stdcoding) (cdr stdcoding)))
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
871 ;; ;; The command has completed, let's decode.
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
872 ;; (goto-char (point-max))
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
873 ;; (delete-char -1) ;Delete final newline.
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
874 ;; (while (re-search-backward "^>" nil t)
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
875 ;; (delete-char 1))
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
876 ;; (current-buffer))))
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
877
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
878 ;;; Misc ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
879
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
880 (defcustom mpc-mpd-music-directory nil
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
881 "Location of MPD's music directory."
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
882 :type '(choice (const nil) directory))
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
883
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
884 (defcustom mpc-data-directory
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
885 (if (and (not (file-directory-p "~/.mpc"))
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
886 (file-directory-p "~/.emacs.d"))
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
887 "~/.emacs.d/mpc" "~/.mpc")
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
888 "Directory where MPC.el stores auxiliary data."
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
889 :type 'directory)
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
890
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
891 (defun mpc-data-directory ()
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
892 (unless (file-directory-p mpc-data-directory)
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
893 (make-directory mpc-data-directory))
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
894 mpc-data-directory)
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
895
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
896 (defun mpc-file-local-copy (file)
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
897 ;; Try to set mpc-mpd-music-directory.
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
898 (when (and (null mpc-mpd-music-directory)
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
899 (string-match "\\`localhost" mpc-host))
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
900 (let ((files '("~/.mpdconf" "/etc/mpd.conf"))
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
901 file)
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
902 (while (and files (not file))
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
903 (if (file-exists-p (car files)) (setq file (car files)))
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
904 (setq files (cdr files)))
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
905 (with-temp-buffer
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
906 (ignore-errors (insert-file-contents file))
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
907 (goto-char (point-min))
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
908 (if (re-search-forward "^music_directory[ ]+\"\\([^\"]+\\)\"")
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
909 (setq mpc-mpd-music-directory
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
910 (match-string 1))))))
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
911 ;; Use mpc-mpd-music-directory if applicable, or else try to use the
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
912 ;; `download' command, although it's never been accepted in `mpd' :-(
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
913 (if (and mpc-mpd-music-directory
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
914 (file-exists-p (expand-file-name file mpc-mpd-music-directory)))
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
915 (expand-file-name file mpc-mpd-music-directory)
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
916 ;; (let ((aux (expand-file-name (replace-regexp-in-string "[/]" "|" file)
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
917 ;; (mpc-data-directory))))
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
918 ;; (unless (file-exists-p aux)
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
919 ;; (condition-case err
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
920 ;; (with-local-quit
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
921 ;; (with-current-buffer (mpc-cmd-download file)
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
922 ;; (write-region (point-min) (point-max) aux)
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
923 ;; (kill-buffer (current-buffer))))
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
924 ;; (mpc-proc-error (message "Download error: %s" err) (setq aux nil))))
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
925 ;; aux)
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
926 ))
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
927
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
928 ;;; Formatter ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
929
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
930 (defun mpc-secs-to-time (secs)
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
931 (if (stringp secs) (setq secs (string-to-number secs)))
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
932 (if (>= secs (* 60 100)) ;More than 100 minutes.
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
933 (format "%dh%02d" ;"%d:%02d:%02d"
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
934 (/ secs 3600) (% (/ secs 60) 60)) ;; (% secs 60)
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
935 (format "%d:%02d" (/ secs 60) (% secs 60))))
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
936
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
937 (defvar mpc-tempfiles nil)
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
938 (defconst mpc-tempfiles-reftable (make-hash-table :weakness 'key))
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
939
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
940 (defun mpc-tempfiles-clean ()
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
941 (let ((live ()))
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
942 (maphash (lambda (k v) (push v live)) mpc-tempfiles-reftable)
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
943 (dolist (f mpc-tempfiles)
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
944 (unless (member f live) (ignore-errors (delete-file f))))
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
945 (setq mpc-tempfiles live)))
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
946
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
947 (defun mpc-tempfiles-add (key file)
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
948 (mpc-tempfiles-clean)
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
949 (puthash key file mpc-tempfiles-reftable)
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
950 (push file mpc-tempfiles))
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
951
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
952 (defun mpc-format (format-spec info &optional hscroll)
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
953 "Format the INFO according to FORMAT-SPEC, inserting the result at point."
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
954 (let* ((pos 0)
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
955 (start (point))
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
956 (col (if hscroll (- hscroll) 0))
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
957 (insert (lambda (str)
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
958 (cond
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
959 ((>= col 0) (insert str))
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
960 (t (insert (substring str (min (length str) (- col))))))))
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
961 (pred nil))
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
962 (while (string-match "%\\(?:%\\|\\(-\\)?\\([0-9]+\\)?{\\([[:alpha:]][[:alnum:]]*\\)\\(?:-\\([^}]+\\)\\)?}\\)" format-spec pos)
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
963 (let ((pre-text (substring format-spec pos (match-beginning 0))))
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
964 (funcall insert pre-text)
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
965 (setq col (+ col (string-width pre-text))))
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
966 (setq pos (match-end 0))
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
967 (if (null (match-end 3))
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
968 (progn
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
969 (funcall insert "%")
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
970 (setq col (+ col 1)))
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
971 (let* ((size (match-string 2 format-spec))
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
972 (tag (intern (match-string 3 format-spec)))
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
973 (post (match-string 4 format-spec))
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
974 (right-align (match-end 1))
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
975 (text
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
976 (if (eq info 'self) (symbol-name tag)
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
977 (case tag
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
978 ((Time Duration)
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
979 (let ((time (cdr (or (assq 'time info) (assq 'Time info)))))
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
980 (setq pred (list nil)) ;Just assume it's never eq.
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
981 (when time
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
982 (mpc-secs-to-time (if (and (eq tag 'Duration)
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
983 (string-match ":" time))
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
984 (substring time (match-end 0))
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
985 time)))))
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
986 (Cover
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
987 (let* ((dir (file-name-directory (cdr (assq 'file info))))
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
988 (cover (concat dir "cover.jpg"))
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
989 (file (condition-case err
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
990 (mpc-file-local-copy cover)
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
991 (error (message "MPC: %s" err))))
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
992 image)
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
993 ;; (debug)
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
994 (push `(equal ',dir (file-name-directory (cdr (assq 'file info)))) pred)
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
995 (if (null file)
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
996 ;; Make sure we return something on which we can
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
997 ;; place the `mpc-pred' property, as
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
998 ;; a negative-cache. We could also use
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
999 ;; a default cover.
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
1000 (progn (setq size nil) " ")
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
1001 (if (null size) (setq image (create-image file))
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
1002 (let ((tempfile (make-temp-file "mpc" nil ".jpg")))
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
1003 (call-process "convert" nil nil nil
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
1004 "-scale" size file tempfile)
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
1005 (setq image (create-image tempfile))
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
1006 (mpc-tempfiles-add image tempfile)))
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
1007 (setq size nil)
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
1008 (propertize dir 'display image))))
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
1009 (t (let ((val (cdr (assq tag info))))
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
1010 ;; For Streaming URLs, there's no other info
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
1011 ;; than the URL in `file'. Pretend it's in `Title'.
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
1012 (when (and (null val) (eq tag 'Title))
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
1013 (setq val (cdr (assq 'file info))))
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
1014 (push `(equal ',val (cdr (assq ',tag info))) pred)
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
1015 val)))))
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
1016 (space (when size
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
1017 (setq size (string-to-number size))
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
1018 (propertize " " 'display
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
1019 (list 'space :align-to (+ col size)))))
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
1020 (textwidth (if text (string-width text) 0))
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
1021 (postwidth (if post (string-width post) 0)))
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
1022 (when text
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
1023 (let ((display
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
1024 (if (and size
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
1025 (> (+ postwidth textwidth) size))
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
1026 ;; This doesn't even obey double-width chars :-(
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
1027 (propertize
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
1028 (if (zerop (- size postwidth 1))
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
1029 (substring text 0 1)
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
1030 (concat (substring text 0 (- size postwidth textwidth 1)) "…"))
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
1031 'help-echo text)
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
1032 text)))
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
1033 (when (memq tag '(Artist Album Composer)) ;FIXME: wrong list.
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
1034 (setq display
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
1035 (propertize display
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
1036 'mouse-face 'highlight
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
1037 'follow-link t
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
1038 'keymap `(keymap
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
1039 (mouse-2
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
1040 . (lambda ()
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
1041 (interactive)
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
1042 (mpc-constraints-push 'noerror)
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
1043 (mpc-constraints-restore
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
1044 ',(list (list tag text)))))))))
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
1045 (funcall insert
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
1046 (concat (when size
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
1047 (propertize " " 'display
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
1048 (list 'space :align-to
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
1049 (+ col
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
1050 (if (and size right-align)
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
1051 (- size postwidth textwidth)
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
1052 0)))))
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
1053 display post))))
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
1054 (if (null size) (setq col (+ col textwidth postwidth))
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
1055 (insert space)
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
1056 (setq col (+ col size))))))
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
1057 (put-text-property start (point) 'mpc-pred
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
1058 `(lambda (info) (and ,@(nreverse pred))))))
|
106354
|
1059
|
106342
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
1060 ;;; The actual UI code ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
1061
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
1062 (defvar mpc-mode-map
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
1063 (let ((map (make-keymap)))
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
1064 (suppress-keymap map)
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
1065 ;; (define-key map "\e" 'mpc-stop)
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
1066 (define-key map "q" 'mpc-quit)
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
1067 (define-key map "\r" 'mpc-select)
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
1068 (define-key map [(shift return)] 'mpc-select-toggle)
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
1069 (define-key map [mouse-2] 'mpc-select)
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
1070 (define-key map [S-mouse-2] 'mpc-select-extend)
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
1071 (define-key map [C-mouse-2] 'mpc-select-toggle)
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
1072 (define-key map [drag-mouse-2] 'mpc-drag-n-drop)
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
1073 ;; We use `always' because a binding to t is like a binding to nil.
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
1074 (define-key map [follow-link] 'always)
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
1075 ;; Doesn't work because the first click changes the buffer, so the second
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
1076 ;; is applied elsewhere :-(
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
1077 ;; (define-key map [(double mouse-2)] 'mpc-play-at-point)
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
1078 (define-key map "p" 'mpc-pause)
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
1079 map))
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
1080
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
1081 (easy-menu-define mpc-mode-menu mpc-mode-map
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
1082 "Menu for MPC.el."
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
1083 '("MPC.el"
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
1084 ["Add new browser" mpc-tagbrowser]
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
1085 ["Update DB" mpc-update]
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
1086 ["Quit" mpc-quit]))
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
1087
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
1088 (defvar mpc-tool-bar-map
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
1089 (let ((map (make-sparse-keymap)))
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
1090 (tool-bar-local-item "mpc/prev" 'mpc-prev 'prev map
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
1091 :enable '(not (equal (cdr (assq 'state mpc-status)) "stop")))
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
1092 ;; FIXME: how can we bind it to the down-event?
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
1093 (tool-bar-local-item "mpc/rewind" 'mpc-rewind 'rewind map
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
1094 :enable '(not (equal (cdr (assq 'state mpc-status)) "stop"))
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
1095 :button '(:toggle . (and mpc--faster-toggle-timer
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
1096 (not mpc--faster-toggle-forward))))
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
1097 ;; We could use a single toggle command for pause/play, with 2 different
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
1098 ;; icons depending on whether or not it's selected, but then it'd have
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
1099 ;; to be a toggle-button, thus displayed depressed in one of the
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
1100 ;; two states :-(
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
1101 (tool-bar-local-item "mpc/pause" 'mpc-pause 'pause map
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
1102 :visible '(equal (cdr (assq 'state mpc-status)) "play")
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
1103 :help "Pause/play")
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
1104 (tool-bar-local-item "mpc/play" 'mpc-play 'play map
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
1105 :visible '(not (equal (cdr (assq 'state mpc-status)) "play"))
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
1106 :help "Play/pause")
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
1107 ;; FIXME: how can we bind it to the down-event?
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
1108 (tool-bar-local-item "mpc/ffwd" 'mpc-ffwd 'ffwd map
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
1109 :enable '(not (equal (cdr (assq 'state mpc-status)) "stop"))
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
1110 :button '(:toggle . (and mpc--faster-toggle-timer
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
1111 mpc--faster-toggle-forward)))
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
1112 (tool-bar-local-item "mpc/next" 'mpc-next 'next map
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
1113 :enable '(not (equal (cdr (assq 'state mpc-status)) "stop")))
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
1114 (tool-bar-local-item "mpc/stop" 'mpc-stop 'stop map)
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
1115 (tool-bar-local-item "mpc/add" 'mpc-playlist-add 'add map
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
1116 :help "Append to the playlist")
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
1117 map))
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
1118
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
1119 (define-derived-mode mpc-mode fundamental-mode "MPC"
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
1120 "Major mode for the features common to all buffers of MPC."
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
1121 (buffer-disable-undo)
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
1122 (setq buffer-read-only t)
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
1123 (set (make-local-variable 'tool-bar-map) mpc-tool-bar-map)
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
1124 (set (make-local-variable 'truncate-lines) t))
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
1125
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
1126 ;;; The mpc-status-mode buffer ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
1127
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
1128 (define-derived-mode mpc-status-mode mpc-mode "MPC-Status"
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
1129 "Major mode to display MPC status info."
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
1130 (set (make-local-variable 'mode-line-format)
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
1131 '("%e" mode-line-frame-identification mode-line-buffer-identification))
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
1132 (set (make-local-variable 'window-area-factor) 3)
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
1133 (set (make-local-variable 'header-line-format) '("MPC " mpc-volume)))
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
1134
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
1135 (defvar mpc-status-buffer-format
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
1136 '("%-5{Time} / %{Duration} %2{Disc--}%4{Track}" "%{Title}" "%{Album}" "%{Artist}" "%128{Cover}"))
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
1137
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
1138 (defun mpc-status-buffer-refresh ()
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
1139 (let ((buf (mpc-proc-buffer (mpc-proc) 'status)))
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
1140 (when (buffer-live-p buf)
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
1141 (with-current-buffer buf
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
1142 (save-excursion
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
1143 (goto-char (point-min))
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
1144 (when (assq 'file mpc-status)
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
1145 (let ((inhibit-read-only t))
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
1146 (dolist (spec mpc-status-buffer-format)
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
1147 (let ((pred (get-text-property (point) 'mpc-pred)))
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
1148 (if (and pred (funcall pred mpc-status))
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
1149 (forward-line)
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
1150 (delete-region (point) (line-beginning-position 2))
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
1151 (ignore-errors (mpc-format spec mpc-status))
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
1152 (insert "\n"))))
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
1153 (unless (eobp) (delete-region (point) (point-max))))))))))
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
1154
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
1155 (defun mpc-status-buffer-show ()
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
1156 (interactive)
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
1157 (let* ((buf (mpc-proc-buffer (mpc-proc) 'status))
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
1158 (songs-buf (mpc-proc-buffer (mpc-proc) 'songs))
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
1159 (songs-win (if songs-buf (get-buffer-window songs-buf 0))))
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
1160 (unless (buffer-live-p buf)
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
1161 (setq buf (get-buffer-create "*MPC-Status*"))
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
1162 (with-current-buffer buf
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
1163 (mpc-status-mode))
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
1164 (mpc-proc-buffer (mpc-proc) 'status buf))
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
1165 (if (null songs-win) (pop-to-buffer buf)
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
1166 (let ((win (split-window songs-win 20 t)))
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
1167 (set-window-dedicated-p songs-win nil)
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
1168 (set-window-buffer songs-win buf)
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
1169 (set-window-dedicated-p songs-win 'soft)))))
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
1170
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
1171 ;;; Selection management;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
1172
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
1173 (defvar mpc-separator-ol nil)
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
1174
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
1175 (defvar mpc-select nil)
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
1176 (make-variable-buffer-local 'mpc-select)
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
1177
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
1178 (defmacro mpc-select-save (&rest body)
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
1179 "Execute BODY and restore the selection afterwards."
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
1180 (declare (indent 0) (debug t))
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
1181 `(let ((selection (mpc-select-get-selection))
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
1182 (position (cons (buffer-substring-no-properties
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
1183 (line-beginning-position) (line-end-position))
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
1184 (current-column))))
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
1185 ,@body
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
1186 (mpc-select-restore selection)
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
1187 (goto-char (point-min))
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
1188 (if (re-search-forward
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
1189 (concat "^" (regexp-quote (car position)) "$")
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
1190 (if (overlayp mpc-separator-ol)
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
1191 (overlay-end mpc-separator-ol))
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
1192 t)
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
1193 (move-to-column (cdr position)))
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
1194 (let ((win (get-buffer-window (current-buffer) 0)))
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
1195 (if win (set-window-point win (point))))))
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
1196
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
1197 (defun mpc-select-get-selection ()
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
1198 (mapcar (lambda (ol)
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
1199 (buffer-substring-no-properties
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
1200 (overlay-start ol) (1- (overlay-end ol))))
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
1201 mpc-select))
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
1202
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
1203 (defun mpc-select-restore (selection)
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
1204 ;; Restore the selection. I.e. move the overlays back to their
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
1205 ;; corresponding location. Actually which overlay is used for what
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
1206 ;; doesn't matter.
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
1207 (mapc 'delete-overlay mpc-select)
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
1208 (setq mpc-select nil)
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
1209 (dolist (elem selection)
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
1210 ;; After an update, some elements may have disappeared.
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
1211 (goto-char (point-min))
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
1212 (when (re-search-forward
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
1213 (concat "^" (regexp-quote elem) "$") nil t)
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
1214 (mpc-select-make-overlay)))
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
1215 (when mpc-tag (mpc-tagbrowser-all-select))
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
1216 (beginning-of-line))
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
1217
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
1218 (defun mpc-select-make-overlay ()
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
1219 (assert (not (get-char-property (point) 'mpc-select)))
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
1220 (let ((ol (make-overlay
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
1221 (line-beginning-position) (line-beginning-position 2))))
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
1222 (overlay-put ol 'mpc-select t)
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
1223 (overlay-put ol 'face 'region)
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
1224 (overlay-put ol 'evaporate t)
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
1225 (push ol mpc-select)))
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
1226
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
1227 (defun mpc-select (&optional event)
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
1228 "Select the tag value at point."
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
1229 (interactive (list last-nonmenu-event))
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
1230 (mpc-event-set-point event)
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
1231 (if (and (bolp) (eobp)) (forward-line -1))
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
1232 (mapc 'delete-overlay mpc-select)
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
1233 (setq mpc-select nil)
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
1234 (if (mpc-tagbrowser-all-p)
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
1235 nil
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
1236 (mpc-select-make-overlay))
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
1237 (when mpc-tag
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
1238 (mpc-tagbrowser-all-select)
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
1239 (mpc-selection-refresh)))
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
1240
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
1241 (defun mpc-select-toggle (&optional event)
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
1242 "Toggle the selection of the tag value at point."
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
1243 (interactive (list last-nonmenu-event))
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
1244 (mpc-event-set-point event)
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
1245 (save-excursion
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
1246 (cond
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
1247 ;; The line is already selected: deselect it.
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
1248 ((get-char-property (point) 'mpc-select)
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
1249 (let ((ols nil))
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
1250 (dolist (ol mpc-select)
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
1251 (if (and (<= (overlay-start ol) (point))
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
1252 (> (overlay-end ol) (point)))
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
1253 (delete-overlay ol)
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
1254 (push ol ols)))
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
1255 (assert (= (1+ (length ols)) (length mpc-select)))
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
1256 (setq mpc-select ols)))
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
1257 ;; We're trying to select *ALL* additionally to others.
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
1258 ((mpc-tagbrowser-all-p) nil)
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
1259 ;; Select the current line.
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
1260 (t (mpc-select-make-overlay))))
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
1261 (when mpc-tag
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
1262 (mpc-tagbrowser-all-select)
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
1263 (mpc-selection-refresh)))
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
1264
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
1265 (defun mpc-select-extend (&optional event)
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
1266 "Extend the selection up to point."
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
1267 (interactive (list last-nonmenu-event))
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
1268 (mpc-event-set-point event)
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
1269 (if (null mpc-select)
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
1270 ;; If nothing's selected yet, fallback to selecting the elem at point.
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
1271 (mpc-select event)
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
1272 (save-excursion
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
1273 (cond
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
1274 ;; The line is already in a selected area; truncate the area.
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
1275 ((get-char-property (point) 'mpc-select)
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
1276 (let ((before 0)
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
1277 (after 0)
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
1278 (mid (line-beginning-position))
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
1279 start end)
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
1280 (while (and (zerop (forward-line 1))
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
1281 (get-char-property (point) 'mpc-select))
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
1282 (setq end (1+ (point)))
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
1283 (incf after))
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
1284 (goto-char mid)
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
1285 (while (and (zerop (forward-line -1))
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
1286 (get-char-property (point) 'mpc-select))
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
1287 (setq start (point))
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
1288 (incf before))
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
1289 (if (and (= after 0) (= before 0))
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
1290 ;; Shortening an already minimum-size region: do nothing.
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
1291 nil
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
1292 (if (> after before)
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
1293 (setq end mid)
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
1294 (setq start (1+ mid)))
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
1295 (let ((ols '()))
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
1296 (dolist (ol mpc-select)
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
1297 (if (and (>= (overlay-start ol) start)
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
1298 (< (overlay-start ol) end))
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
1299 (delete-overlay ol)
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
1300 (push ol ols)))
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
1301 (setq mpc-select (nreverse ols))))))
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
1302 ;; Extending a prior area. Look for the closest selection.
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
1303 (t
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
1304 (when (mpc-tagbrowser-all-p)
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
1305 (forward-line 1))
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
1306 (let ((before 0)
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
1307 (count 0)
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
1308 (dir 1)
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
1309 (start (line-beginning-position)))
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
1310 (while (and (zerop (forward-line 1))
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
1311 (not (get-char-property (point) 'mpc-select)))
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
1312 (incf count))
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
1313 (unless (get-char-property (point) 'mpc-select)
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
1314 (setq count nil))
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
1315 (goto-char start)
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
1316 (while (and (zerop (forward-line -1))
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
1317 (not (get-char-property (point) 'mpc-select)))
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
1318 (incf before))
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
1319 (unless (get-char-property (point) 'mpc-select)
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
1320 (setq before nil))
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
1321 (when (and before (or (null count) (< before count)))
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
1322 (setq count before)
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
1323 (setq dir -1))
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
1324 (goto-char start)
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
1325 (dotimes (i (1+ (or count 0)))
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
1326 (mpc-select-make-overlay)
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
1327 (forward-line dir))))))
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
1328 (when mpc-tag
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
1329 (mpc-tagbrowser-all-select)
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
1330 (mpc-selection-refresh))))
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
1331
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
1332 ;;; Constraint sets ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
1333
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
1334 (defvar mpc--song-search nil)
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
1335
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
1336 (defun mpc-constraints-get-current (&optional avoid-buf)
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
1337 "Return currently selected set of constraints.
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
1338 If AVOID-BUF is non-nil, it specifies a buffer which should be ignored
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
1339 when constructing the set of constraints."
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
1340 (let ((constraints (if mpc--song-search `((Search ,mpc--song-search))))
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
1341 tag select)
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
1342 (dolist (buf (process-get (mpc-proc) 'buffers))
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
1343 (setq buf (cdr buf))
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
1344 (when (and (setq tag (buffer-local-value 'mpc-tag buf))
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
1345 (not (eq buf avoid-buf))
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
1346 (setq select
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
1347 (with-current-buffer buf (mpc-select-get-selection))))
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
1348 (push (cons tag select) constraints)))
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
1349 constraints))
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
1350
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
1351 (defun mpc-constraints-restore (constraints)
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
1352 (let ((search (assq 'Search constraints)))
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
1353 (setq mpc--song-search (cadr search))
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
1354 (when search (setq constraints (delq search constraints))))
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
1355 (dolist (buf (process-get (mpc-proc) 'buffers))
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
1356 (setq buf (cdr buf))
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
1357 (when (buffer-live-p buf)
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
1358 (let* ((tag (buffer-local-value 'mpc-tag buf))
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
1359 (constraint (assq tag constraints)))
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
1360 (when tag
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
1361 (with-current-buffer buf
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
1362 (mpc-select-restore (cdr constraint)))))))
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
1363 (mpc-selection-refresh))
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
1364
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
1365 ;; I don't get the ring.el code. I think it doesn't do what I need, but
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
1366 ;; then I don't understand when what it does would be useful.
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
1367 (defun mpc-ring-make (size) (cons 0 (cons 0 (make-vector size nil))))
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
1368 (defun mpc-ring-push (ring val)
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
1369 (aset (cddr ring) (car ring) val)
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
1370 (setcar (cdr ring) (max (cadr ring) (1+ (car ring))))
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
1371 (setcar ring (mod (1+ (car ring)) (length (cddr ring)))))
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
1372 (defun mpc-ring-pop (ring)
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
1373 (setcar ring (mod (1- (car ring)) (cadr ring)))
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
1374 (aref (cddr ring) (car ring)))
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
1375
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
1376 (defvar mpc-constraints-ring (mpc-ring-make 10))
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
1377
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
1378 (defun mpc-constraints-push (&optional noerror)
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
1379 "Push the current selection on the ring for later."
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
1380 (interactive)
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
1381 (let ((constraints (mpc-constraints-get-current)))
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
1382 (if (null constraints)
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
1383 (unless noerror (error "No selection to push"))
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
1384 (mpc-ring-push mpc-constraints-ring constraints))))
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
1385
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
1386 (defun mpc-constraints-pop ()
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
1387 "Recall the most recently pushed selection."
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
1388 (interactive)
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
1389 (let ((constraints (mpc-ring-pop mpc-constraints-ring)))
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
1390 (if (null constraints)
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
1391 (error "No selection to return to")
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
1392 (mpc-constraints-restore constraints))))
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
1393
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
1394 ;;; The TagBrowser mode ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
1395
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
1396 (defconst mpc-tagbrowser-all-name (propertize "*ALL*" 'face 'italic))
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
1397 (defvar mpc-tagbrowser-all-ol nil)
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
1398 (make-variable-buffer-local 'mpc-tagbrowser-all-ol)
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
1399 (defvar mpc-tag-name nil) (make-variable-buffer-local 'mpc-tag-name)
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
1400 (defun mpc-tagbrowser-all-p ()
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
1401 (and (eq (point-min) (line-beginning-position))
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
1402 (equal mpc-tagbrowser-all-name
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
1403 (buffer-substring (point-min) (line-end-position)))))
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
1404
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
1405 (define-derived-mode mpc-tagbrowser-mode mpc-mode '("MPC-" mpc-tag-name)
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
1406 (set (make-local-variable 'mode-line-process) '("" mpc-tag-name))
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
1407 (set (make-local-variable 'mode-line-format) nil)
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
1408 (set (make-local-variable 'header-line-format) '("" mpc-tag-name ;; "s"
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
1409 ))
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
1410 (set (make-local-variable 'buffer-undo-list) t)
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
1411 )
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
1412
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
1413 (defun mpc-tagbrowser-refresh ()
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
1414 (mpc-select-save
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
1415 (widen)
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
1416 (goto-char (point-min))
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
1417 (assert (looking-at (regexp-quote mpc-tagbrowser-all-name)))
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
1418 (forward-line 1)
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
1419 (let ((inhibit-read-only t))
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
1420 (delete-region (point) (point-max))
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
1421 (dolist (val (mpc-cmd-list mpc-tag)) (insert val "\n")))
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
1422 (set-buffer-modified-p nil))
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
1423 (mpc-reorder))
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
1424
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
1425 (defun mpc-updated-db ()
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
1426 ;; FIXME: This is not asynchronous, but is run from a process filter.
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
1427 (unless (assq 'updating_db mpc-status)
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
1428 (clrhash mpc--find-memoize)
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
1429 (dolist (buf (process-get (mpc-proc) 'buffers))
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
1430 (setq buf (cdr buf))
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
1431 (when (buffer-local-value 'mpc-tag buf)
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
1432 (with-current-buffer buf (with-local-quit (mpc-tagbrowser-refresh)))))
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
1433 (with-local-quit (mpc-songs-refresh))))
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
1434
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
1435 (defun mpc-tagbrowser-buf (tag)
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
1436 (let ((buf (mpc-proc-buffer (mpc-proc) tag)))
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
1437 (if (buffer-live-p buf) buf
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
1438 (setq buf (get-buffer-create (format "*MPC %ss*" tag)))
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
1439 (mpc-proc-buffer (mpc-proc) tag buf)
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
1440 (with-current-buffer buf
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
1441 (let ((inhibit-read-only t))
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
1442 (erase-buffer)
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
1443 (if (member tag '(Directory))
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
1444 (mpc-tagbrowser-dir-mode)
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
1445 (mpc-tagbrowser-mode))
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
1446 (insert mpc-tagbrowser-all-name "\n"))
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
1447 (forward-line -1)
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
1448 (setq mpc-tag tag)
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
1449 (setq mpc-tag-name
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
1450 (if (string-match "y\\'" (symbol-name tag))
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
1451 (concat (substring (symbol-name tag) 0 -1) "ies")
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
1452 (concat (symbol-name tag) "s")))
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
1453 (mpc-tagbrowser-all-select)
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
1454 (mpc-tagbrowser-refresh)
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
1455 buf))))
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
1456
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
1457 (defvar tag-browser-tagtypes
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
1458 (lazy-completion-table tag-browser-tagtypes
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
1459 (lambda ()
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
1460 (append '("Playlist" "Directory")
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
1461 (mpc-cmd-tagtypes)))))
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
1462
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
1463 (defun mpc-tagbrowser (tag)
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
1464 "Create a new browser for TAG."
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
1465 (interactive
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
1466 (list
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
1467 (let ((completion-ignore-case t))
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
1468 (intern
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
1469 (completing-read "Tag: " tag-browser-tagtypes nil 'require-match)))))
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
1470 (let* ((newbuf (mpc-tagbrowser-buf tag))
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
1471 (win (get-buffer-window newbuf 0)))
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
1472 (if win (select-window win)
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
1473 (if (with-current-buffer (window-buffer (selected-window))
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
1474 (derived-mode-p 'mpc-tagbrowser-mode))
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
1475 (setq win (selected-window))
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
1476 ;; Find a tagbrowser-mode buffer.
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
1477 (let ((buffers (process-get (mpc-proc) 'buffers))
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
1478 buffer)
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
1479 (while
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
1480 (and buffers
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
1481 (not (and (buffer-live-p (setq buffer (cdr (pop buffers))))
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
1482 (with-current-buffer buffer
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
1483 (derived-mode-p 'mpc-tagbrowser-mode))
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
1484 (setq win (get-buffer-window buffer 0))))))))
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
1485 (if (not win)
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
1486 (pop-to-buffer newbuf)
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
1487 (setq win (split-window win nil 'horiz))
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
1488 (set-window-buffer win newbuf)
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
1489 (set-window-dedicated-p win 'soft)
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
1490 (select-window win)
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
1491 (balance-windows-area)))))
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
1492
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
1493 (defun mpc-tagbrowser-all-select ()
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
1494 "Select the special *ALL* entry if no other is selected."
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
1495 (if mpc-select
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
1496 (delete-overlay mpc-tagbrowser-all-ol)
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
1497 (save-excursion
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
1498 (goto-char (point-min))
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
1499 (if mpc-tagbrowser-all-ol
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
1500 (move-overlay mpc-tagbrowser-all-ol
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
1501 (point) (line-beginning-position 2))
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
1502 (let ((ol (make-overlay (point) (line-beginning-position 2))))
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
1503 (overlay-put ol 'face 'region)
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
1504 (overlay-put ol 'evaporate t)
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
1505 (set (make-local-variable 'mpc-tagbrowser-all-ol) ol))))))
|
106354
|
1506
|
106342
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
1507 ;; (defvar mpc-constraints nil)
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
1508 (defun mpc-separator (active)
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
1509 ;; Place a separator mark.
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
1510 (unless mpc-separator-ol
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
1511 (set (make-local-variable 'mpc-separator-ol)
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
1512 (make-overlay (point) (point)))
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
1513 (overlay-put mpc-separator-ol 'after-string
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
1514 (propertize "\n"
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
1515 'face '(:height 0.05 :inverse-video t))))
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
1516 (goto-char (point-min))
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
1517 (forward-line 1)
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
1518 (while
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
1519 (and (member (buffer-substring-no-properties
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
1520 (line-beginning-position) (line-end-position))
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
1521 active)
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
1522 (zerop (forward-line 1))))
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
1523 (if (or (eobp) (null active))
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
1524 (delete-overlay mpc-separator-ol)
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
1525 (move-overlay mpc-separator-ol (1- (point)) (point))))
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
1526
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
1527 (defun mpc-sort (active)
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
1528 ;; Sort the active elements at the front.
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
1529 (let ((inhibit-read-only t))
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
1530 (goto-char (point-min))
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
1531 (if (mpc-tagbrowser-all-p) (forward-line 1))
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
1532 (condition-case nil
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
1533 (sort-subr nil 'forward-line 'end-of-line
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
1534 nil nil
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
1535 (lambda (s1 s2)
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
1536 (setq s1 (buffer-substring-no-properties
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
1537 (car s1) (cdr s1)))
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
1538 (setq s2 (buffer-substring-no-properties
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
1539 (car s2) (cdr s2)))
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
1540 (cond
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
1541 ((member s1 active)
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
1542 (if (member s2 active)
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
1543 (let ((cmp (mpc-compare-strings s1 s2 t)))
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
1544 (and (numberp cmp) (< cmp 0)))
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
1545 t))
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
1546 ((member s2 active) nil)
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
1547 (t (let ((cmp (mpc-compare-strings s1 s2 t)))
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
1548 (and (numberp cmp) (< cmp 0)))))))
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
1549 ;; The comparison predicate arg is new in Emacs-22.
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
1550 (wrong-number-of-arguments
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
1551 (sort-subr nil 'forward-line 'end-of-line
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
1552 (lambda ()
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
1553 (let ((name (buffer-substring-no-properties
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
1554 (point) (line-end-position))))
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
1555 (cond
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
1556 ((member name active) (concat "1" name))
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
1557 (t (concat "2" "name"))))))))))
|
106354
|
1558
|
106342
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
1559 (defvar mpc--changed-selection)
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
1560
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
1561 (defun mpc-reorder (&optional nodeactivate)
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
1562 "Reorder entries based on thre currently active selections.
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
1563 I.e. split the current browser buffer into a first part containing the
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
1564 entries included in the selection, then a separator, and then the entries
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
1565 not included in the selection.
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
1566 Return non-nil if a selection was deactivated."
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
1567 (mpc-select-save
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
1568 (let ((constraints (mpc-constraints-get-current (current-buffer)))
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
1569 (active 'all))
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
1570 ;; (unless (equal constraints mpc-constraints)
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
1571 ;; (set (make-local-variable 'mpc-constraints) constraints)
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
1572 (dolist (cst constraints)
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
1573 (let ((vals (apply 'mpc-union
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
1574 (mapcar (lambda (val)
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
1575 (mpc-cmd-list mpc-tag (car cst) val))
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
1576 (cdr cst)))))
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
1577 (setq active
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
1578 (if (listp active) (mpc-intersection active vals) vals))))
|
106354
|
1579
|
106342
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
1580 (when (and (listp active))
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
1581 ;; Remove the selections if they are all in conflict with
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
1582 ;; other constraints.
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
1583 (let ((deactivate t))
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
1584 (dolist (sel selection)
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
1585 (when (member sel active) (setq deactivate nil)))
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
1586 (when deactivate
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
1587 ;; Variable declared/used by `mpc-select-save'.
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
1588 (when selection
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
1589 (setq mpc--changed-selection t))
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
1590 (unless nodeactivate
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
1591 (setq selection nil)
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
1592 (mapc 'delete-overlay mpc-select)
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
1593 (setq mpc-select nil)
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
1594 (mpc-tagbrowser-all-select)))))
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
1595
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
1596 ;; FIXME: This `mpc-sort' takes a lot of time. Maybe we should
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
1597 ;; be more clever and presume the buffer is mostly sorted already.
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
1598 (mpc-sort (if (listp active) active))
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
1599 (mpc-separator (if (listp active) active)))))
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
1600
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
1601 (defun mpc-selection-refresh ()
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
1602 (let ((mpc--changed-selection t))
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
1603 (while mpc--changed-selection
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
1604 (setq mpc--changed-selection nil)
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
1605 (dolist (buf (process-get (mpc-proc) 'buffers))
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
1606 (setq buf (cdr buf))
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
1607 (when (and (buffer-local-value 'mpc-tag buf)
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
1608 (not (eq buf (current-buffer))))
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
1609 (with-current-buffer buf (mpc-reorder)))))
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
1610 ;; FIXME: reorder the current buffer last and prevent deactivation,
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
1611 ;; since whatever selection we made here is the most recent one
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
1612 ;; and should hence take precedence.
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
1613 (when mpc-tag (mpc-reorder 'nodeactivate))
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
1614 ;; FIXME: comment?
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
1615 (if (and mpc--song-search mpc--changed-selection)
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
1616 (progn
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
1617 (setq mpc--song-search nil)
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
1618 (mpc-selection-refresh))
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
1619 (mpc-songs-refresh))))
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
1620
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
1621 ;;; Hierarchical tagbrowser ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
1622 ;; Todo:
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
1623 ;; - Add a button on each dir to open/close it (?)
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
1624 ;; - add the parent dir on the previous line, greyed-out, if it's not
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
1625 ;; present (because we're in the non-selected part and the parent is
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
1626 ;; in the selected part).
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
1627
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
1628 (defvar mpc-tagbrowser-dir-mode-map
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
1629 (let ((map (make-sparse-keymap)))
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
1630 (set-keymap-parent map mpc-tagbrowser-mode-map)
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
1631 (define-key map [?\M-\C-m] 'mpc-tagbrowser-dir-toggle)
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
1632 map))
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
1633
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
1634 ;; (defvar mpc-tagbrowser-dir-keywords
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
1635 ;; '(mpc-tagbrowser-dir-hide-prefix))
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
1636
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
1637 (define-derived-mode mpc-tagbrowser-dir-mode mpc-tagbrowser-mode '("MPC-" mpc-tag-name)
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
1638 ;; (set (make-local-variable 'font-lock-defaults)
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
1639 ;; '(mpc-tagbrowser-dir-keywords t))
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
1640 )
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
1641
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
1642 ;; (defun mpc-tagbrowser-dir-hide-prefix (limit)
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
1643 ;; (while
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
1644 ;; (let ((prev (buffer-substring (line-beginning-position 0)
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
1645 ;; (line-end-position 0))))
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
1646 ;; (
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
1647
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
1648 (defun mpc-tagbrowser-dir-toggle (event)
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
1649 "Open or close the element at point."
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
1650 (interactive (list last-nonmenu-event))
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
1651 (mpc-event-set-point event)
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
1652 (let ((name (buffer-substring (line-beginning-position)
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
1653 (line-end-position)))
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
1654 (prop (intern mpc-tag)))
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
1655 (if (not (member name (process-get (mpc-proc) prop)))
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
1656 (process-put (mpc-proc) prop
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
1657 (cons name (process-get (mpc-proc) prop)))
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
1658 (let ((new (delete name (process-get (mpc-proc) prop))))
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
1659 (setq name (concat name "/"))
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
1660 (process-put (mpc-proc) prop
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
1661 (delq nil
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
1662 (mapcar (lambda (x)
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
1663 (if (mpc-string-prefix-p name x)
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
1664 nil x))
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
1665 new)))))
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
1666 (mpc-tagbrowser-refresh)))
|
106354
|
1667
|
106342
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
1668
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
1669 ;;; Playlist management ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
1670
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
1671 (defvar mpc-songs-playlist nil
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
1672 "Name of the currently selected playlist, if any.
|
106365
|
1673 A value of t means the main playlist.")
|
106342
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
1674 (make-variable-buffer-local 'mpc-songs-playlist)
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
1675
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
1676 (defun mpc-playlist-create (name)
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
1677 "Save current playlist under name NAME."
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
1678 (interactive "sPlaylist name: ")
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
1679 (mpc-proc-cmd (list "save" name))
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
1680 (let ((buf (mpc-proc-buffer (mpc-proc) 'Playlist)))
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
1681 (when (buffer-live-p buf)
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
1682 (with-current-buffer buf (mpc-tagbrowser-refresh)))))
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
1683
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
1684 (defun mpc-playlist-destroy (name)
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
1685 "Delete playlist named NAME."
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
1686 (interactive
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
1687 (list (completing-read "Delete playlist: " (mpc-cmd-list 'Playlist)
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
1688 nil 'require-match)))
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
1689 (mpc-proc-cmd (list "rm" name))
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
1690 (let ((buf (mpc-proc-buffer (mpc-proc) 'Playlist)))
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
1691 (when (buffer-live-p buf)
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
1692 (with-current-buffer buf (mpc-tagbrowser-refresh)))))
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
1693
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
1694 (defun mpc-playlist-rename (oldname newname)
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
1695 "Rename playlist OLDNAME to NEWNAME."
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
1696 (interactive
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
1697 (let* ((oldname (if (and (eq mpc-tag 'Playlist) (null current-prefix-arg))
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
1698 (buffer-substring (line-beginning-position)
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
1699 (line-end-position))
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
1700 (completing-read "Rename playlist: "
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
1701 (mpc-cmd-list 'Playlist)
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
1702 nil 'require-match)))
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
1703 (newname (read-string (format "Rename '%s' to: " oldname))))
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
1704 (if (zerop (length newname))
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
1705 (error "Aborted")
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
1706 (list oldname newname))))
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
1707 (mpc-proc-cmd (list "rename" oldname newname))
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
1708 (let ((buf (mpc-proc-buffer (mpc-proc) 'Playlist)))
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
1709 (if (buffer-live-p buf)
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
1710 (with-current-buffer buf (mpc-tagbrowser-refresh)))))
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
1711
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
1712 (defun mpc-playlist ()
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
1713 "Show the current playlist."
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
1714 (interactive)
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
1715 (mpc-constraints-push 'noerror)
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
1716 (mpc-constraints-restore '()))
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
1717
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
1718 (defun mpc-playlist-add ()
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
1719 "Add the selection to the playlist."
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
1720 (interactive)
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
1721 (let ((songs (mapcar #'car (mpc-songs-selection))))
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
1722 (mpc-cmd-add songs)
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
1723 (message "Appended %d songs" (length songs))
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
1724 ;; Return the songs added. Used in `mpc-play'.
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
1725 songs))
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
1726
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
1727 (defun mpc-playlist-delete ()
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
1728 "Remove the selected songs from the playlist."
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
1729 (interactive)
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
1730 (unless mpc-songs-playlist
|
106697
|
1731 (error "The selected songs aren't part of a playlist"))
|
106342
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
1732 (let ((song-poss (mapcar #'cdr (mpc-songs-selection))))
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
1733 (mpc-cmd-delete song-poss mpc-songs-playlist)
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
1734 (mpc-songs-refresh)
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
1735 (message "Deleted %d songs" (length song-poss))))
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
1736
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
1737 ;;; Volume management ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
1738
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
1739 (defvar mpc-volume-map
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
1740 (let ((map (make-sparse-keymap)))
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
1741 (define-key map [down-mouse-1] 'mpc-volume-mouse-set)
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
1742 (define-key map [mouse-1] 'ignore)
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
1743 (define-key map [header-line down-mouse-1] 'mpc-volume-mouse-set)
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
1744 (define-key map [header-line mouse-1] 'ignore)
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
1745 (define-key map [mode-line down-mouse-1] 'mpc-volume-mouse-set)
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
1746 (define-key map [mode-line mouse-1] 'ignore)
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
1747 map))
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
1748
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
1749 (defvar mpc-volume nil) (put 'mpc-volume 'risky-local-variable t)
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
1750
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
1751 (defun mpc-volume-refresh ()
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
1752 ;; Maintain the volume.
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
1753 (setq mpc-volume
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
1754 (mpc-volume-widget
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
1755 (string-to-number (cdr (assq 'volume mpc-status))))))
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
1756
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
1757 (defvar mpc-volume-step 5)
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
1758
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
1759 (defun mpc-volume-mouse-set (&optional event)
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
1760 "Change volume setting."
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
1761 (interactive (list last-nonmenu-event))
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
1762 (let* ((posn (event-start event))
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
1763 (diff
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
1764 (if (memq (if (stringp (car-safe (posn-object posn)))
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
1765 (aref (car (posn-object posn)) (cdr (posn-object posn)))
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
1766 (with-current-buffer (window-buffer (posn-window posn))
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
1767 (char-after (posn-point posn))))
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
1768 '(?◁ ?<))
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
1769 (- mpc-volume-step) mpc-volume-step))
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
1770 (newvol (+ (string-to-number (cdr (assq 'volume mpc-status))) diff)))
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
1771 (mpc-proc-cmd (list "setvol" newvol) 'mpc-status-refresh)
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
1772 (message "Set MPD volume to %s%%" newvol)))
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
1773
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
1774 (defun mpc-volume-widget (vol &optional size)
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
1775 (unless size (setq size 12.5))
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
1776 (let ((scaledvol (* (/ vol 100.0) size)))
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
1777 ;; (message "Volume sizes: %s - %s" (/ vol fact) (/ (- 100 vol) fact))
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
1778 (list (propertize "<" ;; "◁"
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
1779 ;; 'face 'default
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
1780 'keymap mpc-volume-map
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
1781 'face '(:box (:line-width -2 :style pressed-button))
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
1782 'mouse-face '(:box (:line-width -2 :style released-button)))
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
1783 " "
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
1784 (propertize "a"
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
1785 'display (list 'space :width scaledvol)
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
1786 'face '(:inverse-video t
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
1787 :box (:line-width -2 :style released-button)))
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
1788 (propertize "a"
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
1789 'display (list 'space :width (- size scaledvol))
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
1790 'face '(:box (:line-width -2 :style released-button)))
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
1791 " "
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
1792 (propertize ">" ;; "▷"
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
1793 ;; 'face 'default
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
1794 'keymap mpc-volume-map
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
1795 'face '(:box (:line-width -2 :style pressed-button))
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
1796 'mouse-face '(:box (:line-width -2 :style released-button))))))
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
1797
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
1798 ;;; MPC songs mode ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
1799
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
1800 (defvar mpc-current-song nil) (put 'mpc-current-song 'risky-local-variable t)
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
1801 (defvar mpc-current-updating nil) (put 'mpc-current-updating 'risky-local-variable t)
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
1802 (defvar mpc-songs-format-description nil) (put 'mpc-songs-format-description 'risky-local-variable t)
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
1803
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
1804 (defvar mpc-previous-window-config nil)
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
1805
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
1806 (defvar mpc-songs-mode-map
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
1807 (let ((map (make-sparse-keymap)))
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
1808 (set-keymap-parent map mpc-mode-map)
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
1809 (define-key map [remap mpc-select] 'mpc-songs-jump-to)
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
1810 map))
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
1811
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
1812 (defvar mpc-songpointer-set-visible nil)
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
1813
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
1814 (defvar mpc-songs-hashcons (make-hash-table :test 'equal :weakness t)
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
1815 "Make song file name objects unique via hash consing.
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
1816 This is used so that they can be compared with `eq', which is needed for
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
1817 `text-property-any'.")
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
1818 (defun mpc-songs-hashcons (name)
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
1819 (or (gethash name mpc-songs-hashcons) (puthash name name mpc-songs-hashcons)))
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
1820 (defcustom mpc-songs-format "%2{Disc--}%3{Track} %-5{Time} %25{Title} %20{Album} %20{Artist} %10{Date}"
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
1821 "Format used to display each song in the list of songs."
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
1822 :type 'string)
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
1823
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
1824 (defvar mpc-songs-totaltime)
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
1825
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
1826 (defun mpc-songs-refresh ()
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
1827 (let ((buf (mpc-proc-buffer (mpc-proc) 'songs)))
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
1828 (when (buffer-live-p buf)
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
1829 (with-current-buffer buf
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
1830 (let ((constraints (mpc-constraints-get-current (current-buffer)))
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
1831 (dontsort nil)
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
1832 (inhibit-read-only t)
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
1833 (totaltime 0)
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
1834 (curline (cons (count-lines (point-min)
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
1835 (line-beginning-position))
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
1836 (buffer-substring (line-beginning-position)
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
1837 (line-end-position))))
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
1838 active)
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
1839 (setq mpc-songs-playlist nil)
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
1840 (if (null constraints)
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
1841 ;; When there are no constraints, rather than show the list of
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
1842 ;; all songs (which could take a while to download and
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
1843 ;; format), we show the current playlist.
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
1844 ;; FIXME: it would be good to be able to show the complete
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
1845 ;; list, but that would probably require us to format it
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
1846 ;; on-the-fly to make it bearable.
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
1847 (setq dontsort t
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
1848 mpc-songs-playlist t
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
1849 active (mpc-proc-buf-to-alists
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
1850 (mpc-proc-cmd "playlistinfo")))
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
1851 (dolist (cst constraints)
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
1852 (if (and (eq (car cst) 'Playlist)
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
1853 (= 1 (length (cdr cst))))
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
1854 (setq mpc-songs-playlist (cadr cst)))
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
1855 ;; We don't do anything really special here for playlists,
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
1856 ;; because it's unclear what's a correct "union" of playlists.
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
1857 (let ((vals (apply 'mpc-union
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
1858 (mapcar (lambda (val)
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
1859 (mpc-cmd-find (car cst) val))
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
1860 (cdr cst)))))
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
1861 (setq active (if (null active)
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
1862 (progn
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
1863 (if (eq (car cst) 'Playlist)
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
1864 (setq dontsort t))
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
1865 vals)
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
1866 (if (or dontsort
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
1867 ;; Try to preserve ordering and
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
1868 ;; repetitions from playlists.
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
1869 (not (eq (car cst) 'Playlist)))
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
1870 (mpc-intersection active vals
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
1871 (lambda (x) (assq 'file x)))
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
1872 (setq dontsort t)
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
1873 (mpc-intersection vals active
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
1874 (lambda (x) (assq 'file x)))))))))
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
1875 (mpc-select-save
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
1876 (erase-buffer)
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
1877 ;; Sorting songs is surprisingly difficult: when comparing two
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
1878 ;; songs with the same album name but different artist name, you
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
1879 ;; have to know whether these are two different albums (with the
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
1880 ;; same name) or a single album (typically a compilation).
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
1881 ;; I punt on it and just use file-name sorting, which does the
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
1882 ;; right thing if your library is properly arranged.
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
1883 (dolist (song (if dontsort active
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
1884 (sort active
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
1885 (lambda (song1 song2)
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
1886 (let ((cmp (mpc-compare-strings
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
1887 (cdr (assq 'file song1))
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
1888 (cdr (assq 'file song2)))))
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
1889 (and (integerp cmp) (< cmp 0)))))))
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
1890 (incf totaltime (string-to-number (or (cdr (assq 'Time song)) "0")))
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
1891 (mpc-format mpc-songs-format song)
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
1892 (delete-char (- (skip-chars-backward " "))) ;Remove trailing space.
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
1893 (insert "\n")
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
1894 (put-text-property
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
1895 (line-beginning-position 0) (line-beginning-position)
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
1896 'mpc-file (mpc-songs-hashcons (cdr (assq 'file song))))
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
1897 (let ((pos (assq 'Pos song)))
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
1898 (if pos
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
1899 (put-text-property
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
1900 (line-beginning-position 0) (line-beginning-position)
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
1901 'mpc-file-pos (string-to-number (cdr pos)))))
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
1902 ))
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
1903 (goto-char (point-min))
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
1904 (forward-line (car curline))
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
1905 (when (or (search-forward (cdr curline) nil t)
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
1906 (search-backward (cdr curline) nil t))
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
1907 (beginning-of-line))
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
1908 (set (make-local-variable 'mpc-songs-totaltime)
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
1909 (unless (zerop totaltime)
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
1910 (list " " (mpc-secs-to-time totaltime))))
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
1911 ))))
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
1912 (let ((mpc-songpointer-set-visible t))
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
1913 (mpc-songpointer-refresh)))
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
1914
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
1915 (defun mpc-songs-search (string)
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
1916 "Filter songs to those who include STRING in their metadata."
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
1917 (interactive "sSearch for: ")
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
1918 (setq mpc--song-search
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
1919 (if (zerop (length string)) nil string))
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
1920 (let ((mpc--changed-selection t))
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
1921 (while mpc--changed-selection
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
1922 (setq mpc--changed-selection nil)
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
1923 (dolist (buf (process-get (mpc-proc) 'buffers))
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
1924 (setq buf (cdr buf))
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
1925 (when (buffer-local-value 'mpc-tag buf)
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
1926 (with-current-buffer buf (mpc-reorder))))
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
1927 (mpc-songs-refresh))))
|
106354
|
1928
|
106342
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
1929 (defun mpc-songs-kill-search ()
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
1930 "Turn off the current search restriction."
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
1931 (interactive)
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
1932 (mpc-songs-search nil))
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
1933
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
1934 (defun mpc-songs-selection ()
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
1935 "Return the list of songs currently selected."
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
1936 (let ((buf (mpc-proc-buffer (mpc-proc) 'songs)))
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
1937 (when (buffer-live-p buf)
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
1938 (with-current-buffer buf
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
1939 (save-excursion
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
1940 (let ((files ()))
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
1941 (if mpc-select
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
1942 (dolist (ol mpc-select)
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
1943 (push (cons
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
1944 (get-text-property (overlay-start ol) 'mpc-file)
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
1945 (get-text-property (overlay-start ol) 'mpc-file-pos))
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
1946 files))
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
1947 (goto-char (point-min))
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
1948 (while (not (eobp))
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
1949 (push (cons
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
1950 (get-text-property (point) 'mpc-file)
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
1951 (get-text-property (point) 'mpc-file-pos))
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
1952 files)
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
1953 (forward-line 1)))
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
1954 (nreverse files)))))))
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
1955
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
1956 (defun mpc-songs-jump-to (song-file &optional posn)
|
106365
|
1957 "Jump to song SONG-FILE; interactively, this is the song at point."
|
106342
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
1958 (interactive
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
1959 (let* ((event last-nonmenu-event)
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
1960 (posn (event-end event)))
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
1961 (with-selected-window (posn-window posn)
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
1962 (goto-char (posn-point posn))
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
1963 (list (get-text-property (point) 'mpc-file)
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
1964 posn))))
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
1965 (let* ((plbuf (mpc-proc-cmd "playlist"))
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
1966 (re (concat "^\\([0-9]+\\):" (regexp-quote song-file) "$"))
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
1967 (sn (with-current-buffer plbuf
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
1968 (goto-char (point-min))
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
1969 (when (re-search-forward re nil t)
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
1970 (match-string 1)))))
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
1971 (cond
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
1972 ((null sn) (error "This song is not in the playlist"))
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
1973 ((null (with-current-buffer plbuf (re-search-forward re nil t)))
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
1974 ;; song-file only appears once in the playlist: no ambiguity,
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
1975 ;; we're good to go!
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
1976 (mpc-proc-cmd (list "play" sn)))
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
1977 (t
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
1978 ;; The song appears multiple times in the playlist. If the current
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
1979 ;; buffer holds not only the destination song but also the current
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
1980 ;; song, then we will move in the playlist to the same relative
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
1981 ;; position as in the buffer. Otherwise, we will simply choose the
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
1982 ;; song occurrence closest to the current song.
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
1983 (with-selected-window (posn-window posn)
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
1984 (let* ((cur (and (markerp overlay-arrow-position)
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
1985 (marker-position overlay-arrow-position)))
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
1986 (dest (save-excursion
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
1987 (goto-char (posn-point posn))
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
1988 (line-beginning-position)))
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
1989 (lines (when cur (* (if (< cur dest) 1 -1)
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
1990 (count-lines cur dest)))))
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
1991 (with-current-buffer plbuf
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
1992 (goto-char (point-min))
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
1993 ;; Start the search from the current song.
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
1994 (forward-line (string-to-number
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
1995 (or (cdr (assq 'song mpc-status)) "0")))
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
1996 ;; If the current song is also displayed in the buffer,
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
1997 ;; then try to move to the same relative position.
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
1998 (if lines (forward-line lines))
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
1999 ;; Now search the closest occurrence.
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
2000 (let* ((next (save-excursion
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
2001 (when (re-search-forward re nil t)
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
2002 (cons (point) (match-string 1)))))
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
2003 (prev (save-excursion
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
2004 (when (re-search-backward re nil t)
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
2005 (cons (point) (match-string 1)))))
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
2006 (sn (cdr (if (and next prev)
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
2007 (if (< (- (car next) (point))
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
2008 (- (point) (car prev)))
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
2009 next prev)
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
2010 (or next prev)))))
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
2011 (assert sn)
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
2012 (mpc-proc-cmd (concat "play " sn))))))))))
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
2013
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
2014 (define-derived-mode mpc-songs-mode mpc-mode "MPC-song"
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
2015 (setq mpc-songs-format-description
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
2016 (with-temp-buffer (mpc-format mpc-songs-format 'self) (buffer-string)))
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
2017 (set (make-local-variable 'header-line-format)
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
2018 ;; '("MPC " mpc-volume " " mpc-current-song)
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
2019 (list (propertize " " 'display '(space :align-to 0))
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
2020 ;; 'mpc-songs-format-description
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
2021 '(:eval
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
2022 (let ((hscroll (window-hscroll)))
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
2023 (with-temp-buffer
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
2024 (mpc-format mpc-songs-format 'self hscroll)
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
2025 ;; That would be simpler than the hscroll handling in
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
2026 ;; mpc-format, but currently move-to-column does not
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
2027 ;; recognize :space display properties.
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
2028 ;; (move-to-column hscroll)
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
2029 ;; (delete-region (point-min) (point))
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
2030 (buffer-string))))))
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
2031 (set (make-local-variable 'mode-line-format)
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
2032 '("%e" mode-line-frame-identification mode-line-buffer-identification
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
2033 #(" " 0 3
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
2034 (help-echo "mouse-1: Select (drag to resize)\nmouse-2: Make current window occupy the whole frame\nmouse-3: Remove current window from display"))
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
2035 mode-line-position
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
2036 #(" " 0 2
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
2037 (help-echo "mouse-1: Select (drag to resize)\nmouse-2: Make current window occupy the whole frame\nmouse-3: Remove current window from display"))
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
2038 mpc-songs-totaltime
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
2039 mpc-current-updating
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
2040 #(" " 0 2
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
2041 (help-echo "mouse-1: Select (drag to resize)\nmouse-2: Make current window occupy the whole frame\nmouse-3: Remove current window from display"))
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
2042 (mpc--song-search
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
2043 (:propertize
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
2044 ("Search=\"" mpc--song-search "\"")
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
2045 help-echo "mouse-2: kill this search"
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
2046 follow-link t
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
2047 mouse-face mode-line-highlight
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
2048 keymap (keymap (mode-line keymap
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
2049 (mouse-2 . mpc-songs-kill-search))))
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
2050 (:propertize "NoSearch"
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
2051 help-echo "mouse-2: set a search restriction"
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
2052 follow-link t
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
2053 mouse-face mode-line-highlight
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
2054 keymap (keymap (mode-line keymap (mouse-2 . mpc-songs-search)))))))
|
106354
|
2055
|
106342
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
2056 ;; (set (make-local-variable 'mode-line-process)
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
2057 ;; '("" ;; mpc-volume " "
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
2058 ;; mpc-songs-totaltime
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
2059 ;; mpc-current-updating))
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
2060 )
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
2061
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
2062 (defun mpc-songpointer-set (pos)
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
2063 (let* ((win (get-buffer-window (current-buffer) t))
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
2064 (visible (when win
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
2065 (or mpc-songpointer-set-visible
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
2066 (and (markerp overlay-arrow-position)
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
2067 (eq (marker-buffer overlay-arrow-position)
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
2068 (current-buffer))
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
2069 (<= (window-start win) overlay-arrow-position)
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
2070 (< overlay-arrow-position (window-end win)))))))
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
2071 (unless (local-variable-p 'overlay-arrow-position)
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
2072 (set (make-local-variable 'overlay-arrow-position) (make-marker)))
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
2073 (move-marker overlay-arrow-position pos)
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
2074 ;; If the arrow was visible, try to keep it that way.
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
2075 (if (and visible pos
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
2076 (or (> (window-start win) pos) (>= pos (window-end win t))))
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
2077 (set-window-point win pos))))
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
2078
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
2079 (defun mpc-songpointer-refresh ()
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
2080 (let ((buf (mpc-proc-buffer (mpc-proc) 'songs)))
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
2081 (when (buffer-live-p buf)
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
2082 (with-current-buffer buf
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
2083 (let* ((pos (text-property-any
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
2084 (point-min) (point-max)
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
2085 'mpc-file (mpc-songs-hashcons
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
2086 (cdr (assq 'file mpc-status)))))
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
2087 (other (when pos
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
2088 (save-excursion
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
2089 (goto-char pos)
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
2090 (text-property-any
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
2091 (line-beginning-position 2) (point-max)
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
2092 'mpc-file (mpc-songs-hashcons
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
2093 (cdr (assq 'file mpc-status))))))))
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
2094 (if other
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
2095 ;; The song appears multiple times in the buffer.
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
2096 ;; We need to be careful to choose the right occurrence.
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
2097 (mpc-proc-cmd "playlist" 'mpc-songpointer-refresh-hairy)
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
2098 (mpc-songpointer-set pos)))))))
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
2099
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
2100 (defun mpc-songpointer-context (size plbuf)
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
2101 (with-current-buffer plbuf
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
2102 (goto-char (point-min))
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
2103 (forward-line (string-to-number (or (cdr (assq 'song mpc-status)) "0")))
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
2104 (let ((context-before '())
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
2105 (context-after '()))
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
2106 (save-excursion
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
2107 (dotimes (i size)
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
2108 (when (re-search-backward "^[0-9]+:\\(.*\\)" nil t)
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
2109 (push (mpc-songs-hashcons (match-string 1)) context-before))))
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
2110 ;; Skip the actual current song.
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
2111 (forward-line 1)
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
2112 (dotimes (i size)
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
2113 (when (re-search-forward "^[0-9]+:\\(.*\\)" nil t)
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
2114 (push (mpc-songs-hashcons (match-string 1)) context-after)))
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
2115 ;; If there isn't `size' context, then return nil.
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
2116 (unless (and (< (length context-before) size)
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
2117 (< (length context-after) size))
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
2118 (cons (nreverse context-before) (nreverse context-after))))))
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
2119
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
2120 (defun mpc-songpointer-score (context pos)
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
2121 (let ((count 0))
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
2122 (goto-char pos)
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
2123 (dolist (song (car context))
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
2124 (and (zerop (forward-line -1))
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
2125 (eq (get-text-property (point) 'mpc-file) song)
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
2126 (incf count)))
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
2127 (goto-char pos)
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
2128 (dolist (song (cdr context))
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
2129 (and (zerop (forward-line 1))
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
2130 (eq (get-text-property (point) 'mpc-file) song)
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
2131 (incf count)))
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
2132 count))
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
2133
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
2134 (defun mpc-songpointer-refresh-hairy ()
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
2135 ;; Based on the complete playlist, we should figure out where in the
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
2136 ;; song buffer is the currently playing song.
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
2137 (let ((plbuf (current-buffer))
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
2138 (buf (mpc-proc-buffer (mpc-proc) 'songs)))
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
2139 (when (buffer-live-p buf)
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
2140 (with-current-buffer buf
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
2141 (let* ((context-size 0)
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
2142 (context '(() . ()))
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
2143 (pos (text-property-any
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
2144 (point-min) (point-max)
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
2145 'mpc-file (mpc-songs-hashcons
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
2146 (cdr (assq 'file mpc-status)))))
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
2147 (score 0)
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
2148 (other pos))
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
2149 (while
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
2150 (setq other
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
2151 (save-excursion
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
2152 (goto-char other)
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
2153 (text-property-any
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
2154 (line-beginning-position 2) (point-max)
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
2155 'mpc-file (mpc-songs-hashcons
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
2156 (cdr (assq 'file mpc-status))))))
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
2157 ;; There is an `other' contestant.
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
2158 (let ((other-score (mpc-songpointer-score context other)))
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
2159 (cond
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
2160 ;; `other' is worse: try the next one.
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
2161 ((< other-score score) nil)
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
2162 ;; `other' is better: remember it and then search further.
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
2163 ((> other-score score)
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
2164 (setq pos other)
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
2165 (setq score other-score))
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
2166 ;; Both are equal and increasing the context size won't help.
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
2167 ;; Arbitrarily choose one of the two and keep looking
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
2168 ;; for a better match.
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
2169 ((< score context-size) nil)
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
2170 (t
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
2171 ;; Score is equal and increasing context might help: try it.
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
2172 (incf context-size)
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
2173 (let ((new-context
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
2174 (mpc-songpointer-context context-size plbuf)))
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
2175 (if (null new-context)
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
2176 ;; There isn't more context: choose one arbitrarily
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
2177 ;; and keep looking for a better match elsewhere.
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
2178 (decf context-size)
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
2179 (setq context new-context)
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
2180 (setq score (mpc-songpointer-score context pos))
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
2181 (save-excursion
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
2182 (goto-char other)
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
2183 ;; Go back one line so we find `other' again.
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
2184 (setq other (line-beginning-position 0)))))))))
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
2185 (mpc-songpointer-set pos))))))
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
2186
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
2187 (defun mpc-current-refresh ()
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
2188 ;; Maintain the current data.
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
2189 (mpc-status-buffer-refresh)
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
2190 (setq mpc-current-updating
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
2191 (if (assq 'updating_db mpc-status) " Updating-DB"))
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
2192 (ignore-errors
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
2193 (setq mpc-current-song
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
2194 (when (assq 'file mpc-status)
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
2195 (concat " "
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
2196 (mpc-secs-to-time (cdr (assq 'time mpc-status)))
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
2197 " "
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
2198 (cdr (assq 'Title mpc-status))
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
2199 " ("
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
2200 (cdr (assq 'Artist mpc-status))
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
2201 " / "
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
2202 (cdr (assq 'Album mpc-status))
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
2203 ")"))))
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
2204 (force-mode-line-update t))
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
2205
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
2206 (defun mpc-songs-buf ()
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
2207 (let ((buf (mpc-proc-buffer (mpc-proc) 'songs)))
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
2208 (if (buffer-live-p buf) buf
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
2209 (with-current-buffer (setq buf (get-buffer-create "*MPC-Songs*"))
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
2210 (mpc-proc-buffer (mpc-proc) 'songs buf)
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
2211 (mpc-songs-mode)
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
2212 buf))))
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
2213
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
2214 (defun mpc-update ()
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
2215 "Tell MPD to refresh its database."
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
2216 (interactive)
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
2217 (mpc-cmd-update))
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
2218
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
2219 (defun mpc-quit ()
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
2220 "Quit Music Player Daemon."
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
2221 (interactive)
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
2222 (let* ((proc mpc-proc)
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
2223 (bufs (mapcar 'cdr (if proc (process-get proc 'buffers))))
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
2224 (wins (mapcar (lambda (buf) (get-buffer-window buf 0)) bufs))
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
2225 (song-buf (mpc-songs-buf))
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
2226 frames)
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
2227 ;; Collect all the frames where MPC buffers appear.
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
2228 (dolist (win wins)
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
2229 (when (and win (not (memq (window-frame win) frames)))
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
2230 (push (window-frame win) frames)))
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
2231 (if (and frames song-buf
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
2232 (with-current-buffer song-buf mpc-previous-window-config))
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
2233 (progn
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
2234 (select-frame (car frames))
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
2235 (set-window-configuration
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
2236 (with-current-buffer song-buf mpc-previous-window-config)))
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
2237 ;; Now delete the ones that show nothing else than MPC buffers.
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
2238 (dolist (frame frames)
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
2239 (let ((delete t))
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
2240 (dolist (win (window-list frame))
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
2241 (unless (memq (window-buffer win) bufs) (setq delete nil)))
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
2242 (if delete (ignore-errors (delete-frame frame))))))
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
2243 ;; Then kill the buffers.
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
2244 (mapc 'kill-buffer bufs)
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
2245 (mpc-status-stop)
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
2246 (if proc (delete-process proc))))
|
106354
|
2247
|
106342
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
2248 (defun mpc-stop ()
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
2249 "Stop playing the current queue of songs."
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
2250 (interactive)
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
2251 (mpc-cmd-stop)
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
2252 (mpc-cmd-clear)
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
2253 (mpc-status-refresh))
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
2254
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
2255 (defun mpc-pause ()
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
2256 "Pause playing."
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
2257 (interactive)
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
2258 (mpc-cmd-pause "1"))
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
2259
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
2260 (defun mpc-resume ()
|
106365
|
2261 "Resume playing."
|
106342
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
2262 (interactive)
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
2263 (mpc-cmd-pause "0"))
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
2264
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
2265 (defun mpc-play ()
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
2266 "Start playing whatever is selected."
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
2267 (interactive)
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
2268 (if (member (cdr (assq 'state (mpc-cmd-status))) '("pause"))
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
2269 (mpc-resume)
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
2270 ;; When playing the playlist ends, the playlist isn't cleared, but the
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
2271 ;; user probably doesn't want to re-listen to it before getting to
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
2272 ;; listen to what he just selected.
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
2273 ;; (if (member (cdr (assq 'state (mpc-cmd-status))) '("stop"))
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
2274 ;; (mpc-cmd-clear))
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
2275 ;; Actually, we don't use mpc-play to append to the playlist any more,
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
2276 ;; so we can just always empty the playlist.
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
2277 (mpc-cmd-clear)
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
2278 (if (mpc-playlist-add)
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
2279 (if (member (cdr (assq 'state (mpc-cmd-status))) '("stop"))
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
2280 (mpc-cmd-play))
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
2281 (error "Don't know what to play"))))
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
2282
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
2283 (defun mpc-next ()
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
2284 "Jump to the next song in the queue."
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
2285 (interactive)
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
2286 (mpc-proc-cmd "next")
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
2287 (mpc-status-refresh))
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
2288
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
2289 (defun mpc-prev ()
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
2290 "Jump to the beginning of the current song, or to the previous song."
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
2291 (interactive)
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
2292 (let ((time (cdr (assq 'time mpc-status))))
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
2293 ;; Here we rely on the fact that string-to-number silently ignores
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
2294 ;; everything after a non-digit char.
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
2295 (cond
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
2296 ;; Go back to the beginning of current song.
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
2297 ((and time (> (string-to-number time) 0))
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
2298 (mpc-proc-cmd (list "seekid" (cdr (assq 'songid mpc-status)) 0)))
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
2299 ;; We're at the beginning of the first song of the playlist.
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
2300 ;; Fetch the previous one from `mpc-queue-back'.
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
2301 ;; ((and (zerop (string-to-number (cdr (assq 'song mpc-status))))
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
2302 ;; mpc-queue-back)
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
2303 ;; ;; Because we use cmd-list rather than cmd-play, the queue is not
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
2304 ;; ;; automatically updated.
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
2305 ;; (let ((prev (pop mpc-queue-back)))
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
2306 ;; (push prev mpc-queue)
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
2307 ;; (mpc-proc-cmd
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
2308 ;; (mpc-proc-cmd-list
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
2309 ;; (list (list "add" prev)
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
2310 ;; (list "move" (cdr (assq 'playlistlength mpc-status)) "0")
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
2311 ;; "previous")))))
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
2312 ;; We're at the beginning of a song, but not the first one.
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
2313 (t (mpc-proc-cmd "previous")))
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
2314 (mpc-status-refresh)))
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
2315
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
2316 (defvar mpc-last-seek-time '(0 . 0))
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
2317
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
2318 (defun mpc--faster (event speedup step)
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
2319 "Fast forward."
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
2320 (interactive (list last-nonmenu-event))
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
2321 (let ((repeat-delay (/ (abs (float step)) speedup)))
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
2322 (if (not (memq 'down (event-modifiers event)))
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
2323 (let* ((currenttime (float-time))
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
2324 (last-time (- currenttime (car mpc-last-seek-time))))
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
2325 (if (< last-time (* 0.9 repeat-delay))
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
2326 nil ;; Trottle
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
2327 (let* ((status (if (< last-time 1.0)
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
2328 mpc-status (mpc-cmd-status)))
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
2329 (songid (cdr (assq 'songid status)))
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
2330 (time (if songid
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
2331 (if (< last-time 1.0)
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
2332 (cdr mpc-last-seek-time)
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
2333 (string-to-number
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
2334 (cdr (assq 'time status)))))))
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
2335 (setq mpc-last-seek-time
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
2336 (cons currenttime (setq time (+ time step))))
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
2337 (mpc-proc-cmd (list "seekid" songid time)
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
2338 'mpc-status-refresh))))
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
2339 (let ((status (mpc-cmd-status)))
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
2340 (lexical-let* ((songid (cdr (assq 'songid status)))
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
2341 (step step)
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
2342 (time (if songid (string-to-number
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
2343 (cdr (assq 'time status))))))
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
2344 (let ((timer (run-with-timer
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
2345 t repeat-delay
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
2346 (lambda ()
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
2347 (mpc-proc-cmd (list "seekid" songid
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
2348 (setq time (+ time step)))
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
2349 'mpc-status-refresh)))))
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
2350 (while (mouse-movement-p
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
2351 (event-basic-type (setq event (read-event)))))
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
2352 (cancel-timer timer)))))))
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
2353
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
2354 (defvar mpc--faster-toggle-timer nil)
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
2355 (defun mpc--faster-stop ()
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
2356 (when mpc--faster-toggle-timer
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
2357 (cancel-timer mpc--faster-toggle-timer)
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
2358 (setq mpc--faster-toggle-timer nil)))
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
2359
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
2360 (defun mpc--faster-toggle-refresh ()
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
2361 (if (equal (cdr (assq 'state mpc-status)) "stop")
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
2362 (mpc--faster-stop)))
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
2363
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
2364 (defun mpc--songduration ()
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
2365 (string-to-number
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
2366 (let ((s (cdr (assq 'time mpc-status))))
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
2367 (if (not (string-match ":" s))
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
2368 (error "Unexpected time format %S" s)
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
2369 (substring s (match-end 0))))))
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
2370
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
2371 (defvar mpc--faster-toggle-forward nil)
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
2372 (defvar mpc--faster-acceleration 0.5)
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
2373 (defun mpc--faster-toggle (speedup step)
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
2374 (setq speedup (float speedup))
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
2375 (if mpc--faster-toggle-timer
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
2376 (mpc--faster-stop)
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
2377 (mpc-status-refresh) (mpc-proc-sync)
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
2378 (lexical-let* ((speedup speedup)
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
2379 songid ;The ID of the currently ffwd/rewinding song.
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
2380 songnb ;The position of that song in the playlist.
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
2381 songduration ;The duration of that song.
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
2382 songtime ;The time of the song last time we ran.
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
2383 oldtime ;The timeoftheday last time we ran.
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
2384 prevsongid) ;The song we're in the process leaving.
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
2385 (let ((fun
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
2386 (lambda ()
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
2387 (let ((newsongid (cdr (assq 'songid mpc-status)))
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
2388 (newsongnb (cdr (assq 'song mpc-status))))
|
106354
|
2389
|
106342
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
2390 (if (and (equal prevsongid newsongid)
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
2391 (not (equal prevsongid songid)))
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
2392 ;; We left prevsongid and came back to it. Pretend it
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
2393 ;; didn't happen.
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
2394 (setq newsongid songid))
|
106354
|
2395
|
106342
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
2396 (cond
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
2397 ((null newsongid) (mpc--faster-stop))
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
2398 ((not (equal songid newsongid))
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
2399 ;; We jumped to another song: reset.
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
2400 (setq songid newsongid)
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
2401 (setq songtime (string-to-number
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
2402 (cdr (assq 'time mpc-status))))
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
2403 (setq songduration (mpc--songduration))
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
2404 (setq oldtime (float-time)))
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
2405 ((and (>= songtime songduration) mpc--faster-toggle-forward)
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
2406 ;; Skip to the beginning of the next song.
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
2407 (if (not (equal (cdr (assq 'state mpc-status)) "play"))
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
2408 (mpc-proc-cmd "next" 'mpc-status-refresh)
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
2409 ;; If we're playing, this is done automatically, so we
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
2410 ;; don't need to do anything, or rather we *shouldn't*
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
2411 ;; do anything otherwise there's a race condition where
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
2412 ;; we could skip straight to the next next song.
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
2413 nil))
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
2414 ((and (<= songtime 0) (not mpc--faster-toggle-forward))
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
2415 ;; Skip to the end of the previous song.
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
2416 (setq prevsongid songid)
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
2417 (mpc-proc-cmd "previous"
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
2418 (lambda ()
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
2419 (mpc-status-refresh
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
2420 (lambda ()
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
2421 (setq songid (cdr (assq 'songid mpc-status)))
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
2422 (setq songtime (setq songduration (mpc--songduration)))
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
2423 (setq oldtime (float-time))
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
2424 (mpc-proc-cmd (list "seekid" songid songtime)))))))
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
2425 (t
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
2426 (setq speedup (+ speedup mpc--faster-acceleration))
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
2427 (let ((newstep
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
2428 (truncate (* speedup (- (float-time) oldtime)))))
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
2429 (if (<= newstep 1) (setq newstep 1))
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
2430 (setq oldtime (+ oldtime (/ newstep speedup)))
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
2431 (if (not mpc--faster-toggle-forward)
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
2432 (setq newstep (- newstep)))
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
2433 (setq songtime (min songduration (+ songtime newstep)))
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
2434 (unless (>= songtime songduration)
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
2435 (condition-case nil
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
2436 (mpc-proc-cmd
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
2437 (list "seekid" songid songtime)
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
2438 'mpc-status-refresh)
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
2439 (mpc-proc-error (mpc-status-refresh)))))))
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
2440 (setq songnb newsongnb)))))
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
2441 (setq mpc--faster-toggle-forward (> step 0))
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
2442 (funcall fun) ;Initialize values.
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
2443 (setq mpc--faster-toggle-timer
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
2444 (run-with-timer t 0.3 fun))))))
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
2445
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
2446
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
2447
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
2448 (defvar mpc-faster-speedup 8)
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
2449
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
2450 (defun mpc-ffwd (event)
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
2451 "Fast forward."
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
2452 (interactive (list last-nonmenu-event))
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
2453 ;; (mpc--faster event 4.0 1)
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
2454 (mpc--faster-toggle mpc-faster-speedup 1))
|
106354
|
2455
|
106342
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
2456 (defun mpc-rewind (event)
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
2457 "Fast rewind."
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
2458 (interactive (list last-nonmenu-event))
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
2459 ;; (mpc--faster event 4.0 -1)
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
2460 (mpc--faster-toggle mpc-faster-speedup -1))
|
106354
|
2461
|
|
2462
|
106342
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
2463 (defun mpc-play-at-point (&optional event)
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
2464 (interactive (list last-nonmenu-event))
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
2465 (mpc-select event)
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
2466 (mpc-play))
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
2467
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
2468 ;; (defun mpc-play-tagval ()
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
2469 ;; "Play all the songs of the tag at point."
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
2470 ;; (interactive)
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
2471 ;; (let* ((val (buffer-substring (line-beginning-position) (line-end-position)))
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
2472 ;; (songs (mapcar 'cdar
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
2473 ;; (mpc-proc-buf-to-alists
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
2474 ;; (mpc-proc-cmd (list "find" mpc-tag val))))))
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
2475 ;; (mpc-cmd-add songs)
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
2476 ;; (if (member (cdr (assq 'state (mpc-cmd-status))) '("stop"))
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
2477 ;; (mpc-cmd-play))))
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
2478
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
2479 ;;; Drag'n'drop support ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
2480 ;; Todo:
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
2481 ;; the main thing to do here, is to provide visual feedback during the drag:
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
2482 ;; - change the mouse-cursor.
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
2483 ;; - highlight/select the source and the current destination.
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
2484
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
2485 (defun mpc-drag-n-drop (event)
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
2486 "DWIM for a drag EVENT."
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
2487 (interactive "e")
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
2488 (let* ((start (event-start event))
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
2489 (end (event-end event))
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
2490 (start-buf (window-buffer (posn-window start)))
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
2491 (end-buf (window-buffer (posn-window end)))
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
2492 (songs
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
2493 (with-current-buffer start-buf
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
2494 (goto-char (posn-point start))
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
2495 (if (get-text-property (point) 'mpc-select)
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
2496 ;; FIXME: actually we should only consider the constraints
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
2497 ;; corresponding to the selection in this particular buffer.
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
2498 (mpc-songs-selection)
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
2499 (cond
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
2500 ((and (derived-mode-p 'mpc-songs-mode)
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
2501 (get-text-property (point) 'mpc-file))
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
2502 (list (cons (get-text-property (point) 'mpc-file)
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
2503 (get-text-property (point) 'mpc-file-pos))))
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
2504 ((and mpc-tag (not (mpc-tagbrowser-all-p)))
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
2505 (mapcar (lambda (song)
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
2506 (list (cdr (assq 'file song))))
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
2507 (mpc-cmd-find
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
2508 mpc-tag
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
2509 (buffer-substring (line-beginning-position)
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
2510 (line-end-position)))))
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
2511 (t
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
2512 (error "Unsupported starting position for drag'n'drop gesture")))))))
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
2513 (with-current-buffer end-buf
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
2514 (goto-char (posn-point end))
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
2515 (cond
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
2516 ((eq mpc-tag 'Playlist)
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
2517 ;; Adding elements to a named playlist.
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
2518 (let ((playlist (if (or (mpc-tagbrowser-all-p)
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
2519 (and (bolp) (eolp)))
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
2520 (error "Not a playlist")
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
2521 (buffer-substring (line-beginning-position)
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
2522 (line-end-position)))))
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
2523 (mpc-cmd-add (mapcar 'car songs) playlist)
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
2524 (message "Added %d songs to %s" (length songs) playlist)
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
2525 (if (member playlist
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
2526 (cdr (assq 'Playlist (mpc-constraints-get-current))))
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
2527 (mpc-songs-refresh))))
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
2528 ((derived-mode-p 'mpc-songs-mode)
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
2529 (cond
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
2530 ((null mpc-songs-playlist)
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
2531 (error "The songs shown do not belong to a playlist"))
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
2532 ((eq start-buf end-buf)
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
2533 ;; Moving songs within the shown playlist.
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
2534 (let ((dest-pos (get-text-property (point) 'mpc-file-pos)))
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
2535 (mpc-cmd-move (mapcar 'cdr songs) dest-pos mpc-songs-playlist)
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
2536 (message "Moved %d songs" (length songs))))
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
2537 (t
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
2538 ;; Adding songs to the shown playlist.
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
2539 (let ((dest-pos (get-text-property (point) 'mpc-file-pos))
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
2540 (pl (if (stringp mpc-songs-playlist)
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
2541 (mpc-cmd-find 'Playlist mpc-songs-playlist)
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
2542 (mpc-proc-cmd-to-alist "playlist"))))
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
2543 ;; MPD's protocol does not let us add songs at a particular
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
2544 ;; position in a playlist, so we first have to add them to the
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
2545 ;; end, and then move them to their final destination.
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
2546 (mpc-cmd-add (mapcar 'car songs) mpc-songs-playlist)
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
2547 (mpc-cmd-move (let ((poss '()))
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
2548 (dotimes (i (length songs))
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
2549 (push (+ i (length pl)) poss))
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
2550 (nreverse poss)) dest-pos mpc-songs-playlist)
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
2551 (message "Added %d songs" (length songs)))))
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
2552 (mpc-songs-refresh))
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
2553 (t
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
2554 (error "Unsupported drag'n'drop gesture"))))))
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
2555
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
2556 ;;; Toplevel ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
2557
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
2558 (defcustom mpc-frame-alist '((name . "MPC") (tool-bar-lines . 1)
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
2559 (font . "Sans"))
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
2560 "Alist of frame parameters for the MPC frame."
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
2561 :type 'alist)
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
2562
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
2563 ;;;###autoload
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
2564 (defun mpc ()
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
2565 "Main entry point for MPC."
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
2566 (interactive
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
2567 (progn
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
2568 (if current-prefix-arg
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
2569 (setq mpc-host (read-string "MPD host and port: " nil nil mpc-host)))
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
2570 nil))
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
2571 (let* ((song-buf (mpc-songs-buf))
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
2572 (song-win (get-buffer-window song-buf 0)))
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
2573 (if song-win
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
2574 (select-window song-win)
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
2575 (if (or (window-dedicated-p (selected-window))
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
2576 (window-minibuffer-p))
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
2577 (ignore-errors (select-frame (make-frame mpc-frame-alist)))
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
2578 (with-current-buffer song-buf
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
2579 (set (make-local-variable 'mpc-previous-window-config)
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
2580 (current-window-configuration))))
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
2581 (let* ((win1 (selected-window))
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
2582 (win2 (split-window))
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
2583 (tags mpc-browser-tags))
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
2584 (unless tags (error "Need at least one entry in `mpc-browser-tags'"))
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
2585 (set-window-buffer win2 song-buf)
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
2586 (set-window-dedicated-p win2 'soft)
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
2587 (mpc-status-buffer-show)
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
2588 (while
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
2589 (progn
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
2590 (set-window-buffer win1 (mpc-tagbrowser-buf (pop tags)))
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
2591 (set-window-dedicated-p win1 'soft)
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
2592 tags)
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
2593 (setq win1 (split-window win1 nil 'horiz)))))
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
2594 (balance-windows-area))
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
2595 (mpc-songs-refresh)
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
2596 (mpc-status-refresh))
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
2597
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
2598 (provide 'mpc)
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
2599
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
2600 ;; arch-tag: 4794b2f5-59e6-4f26-b695-650b3e002f37
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
2601 ;;; mpc.el ends here
|