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 (defgroup mpc ()
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
98 "A Client for the Music Player Daemon."
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
99 :prefix "mpc-"
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
100 :group 'multimedia
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
101 :group 'applications)
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
102
|
107541
|
103 (defcustom mpc-browser-tags '(Genre Artist|Composer|Performer
|
|
104 Album|Playlist)
|
106342
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
105 "Tags for which a browser buffer should be created by default."
|
107541
|
106 ;; FIXME: provide a list of tags, for completion.
|
|
107 :type '(repeat symbol))
|
106342
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
108
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
109 ;;; Misc utils ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
110
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
111 (defun mpc-assq-all (key alist)
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
112 (let ((res ()) val)
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
113 (dolist (elem alist)
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
114 (if (and (eq (car elem) key)
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
115 (not (member (setq val (cdr elem)) res)))
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
116 (push val res)))
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
117 (nreverse res)))
|
106354
|
118
|
106342
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
119 (defun mpc-union (&rest lists)
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
120 (let ((res (nreverse (pop lists))))
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
121 (dolist (list lists)
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
122 (let ((seen res)) ;Don't remove duplicates within each list.
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
123 (dolist (elem list)
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
124 (unless (member elem seen) (push elem res)))))
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
125 (nreverse res)))
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
126
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
127 (defun mpc-intersection (l1 l2 &optional selectfun)
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
128 "Return L1 after removing all elements not found in L2.
|
106365
|
129 If SELECTFUN is non-nil, elements aren't compared directly, but instead
|
|
130 they are passed through SELECTFUN before comparison."
|
106342
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
131 (let ((res ()))
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
132 (if selectfun (setq l2 (mapcar selectfun l2)))
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
133 (dolist (elem l1)
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
134 (when (member (if selectfun (funcall selectfun elem) elem) l2)
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
135 (push elem res)))
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
136 (nreverse res)))
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
137
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
138 (defun mpc-event-set-point (event)
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
139 (condition-case nil (posn-set-point (event-end event))
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
140 (error (condition-case nil (mouse-set-point event)
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
141 (error nil)))))
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
142
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
143 (defun mpc-compare-strings (str1 str2 &optional ignore-case)
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
144 "Compare strings STR1 and STR2.
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
145 Contrary to `compare-strings', this tries to get numbers sorted
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
146 numerically rather than lexicographically."
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
147 (let ((res (compare-strings str1 nil nil str2 nil nil ignore-case)))
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
148 (if (not (integerp res)) res
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
149 (let ((index (1- (abs res))))
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
150 (if (or (>= index (length str1)) (>= index (length str2)))
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
151 res
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
152 (let ((digit1 (memq (aref str1 index)
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
153 '(?0 ?1 ?2 ?3 ?4 ?5 ?6 ?7 ?8 ?9)))
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
154 (digit2 (memq (aref str2 index)
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
155 '(?0 ?1 ?2 ?3 ?4 ?5 ?6 ?7 ?8 ?9))))
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
156 (if digit1
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
157 (if digit2
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
158 (let ((num1 (progn (string-match "[0-9]+" str1 index)
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
159 (match-string 0 str1)))
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
160 (num2 (progn (string-match "[0-9]+" str2 index)
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
161 (match-string 0 str2))))
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
162 (cond
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
163 ;; Here we presume that leading zeroes are only used
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
164 ;; for same-length numbers. So we'll incorrectly
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
165 ;; consider that "000" comes after "01", but I don't
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
166 ;; think it matters.
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
167 ((< (length num1) (length num2)) (- (abs res)))
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
168 ((> (length num1) (length num2)) (abs res))
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
169 ((< (string-to-number num1) (string-to-number num2))
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
170 (- (abs res)))
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
171 (t (abs res))))
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
172 ;; "1a" comes before "10", but "0" comes before "a".
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
173 (if (and (not (zerop index))
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
174 (memq (aref str1 (1- index))
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
175 '(?0 ?1 ?2 ?3 ?4 ?5 ?6 ?7 ?8 ?9)))
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
176 (abs res)
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
177 (- (abs res))))
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
178 (if digit2
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
179 ;; "1a" comes before "10", but "0" comes before "a".
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
180 (if (and (not (zerop index))
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
181 (memq (aref str1 (1- index))
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
182 '(?0 ?1 ?2 ?3 ?4 ?5 ?6 ?7 ?8 ?9)))
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
183 (- (abs res))
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
184 (abs res))
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
185 res))))))))
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
186
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
187 (defun mpc-string-prefix-p (str1 str2)
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
188 ;; FIXME: copied from pcvs-util.el.
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
189 "Tell whether STR1 is a prefix of STR2."
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
190 (eq t (compare-strings str2 nil (length str1) str1 nil nil)))
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
191
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
192 ;; This can speed up mpc--song-search significantly. The table may grow
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
193 ;; very large, tho. It's only bounded by the fact that it gets flushed
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
194 ;; whenever the connection is established; which seems to work OK thanks
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
195 ;; to the fact that MPD tends to disconnect fairly often, although our
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
196 ;; constant polling often prevents disconnection.
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
197 (defvar mpc--find-memoize (make-hash-table :test 'equal)) ;; :weakness t
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
198 (defvar mpc-tag nil) (make-variable-buffer-local 'mpc-tag)
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
199
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
200 ;;; Support for the actual connection and MPD command execution ;;;;;;;;;;;;
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
201
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
202 (defcustom mpc-host
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
203 (concat (or (getenv "MPD_HOST") "localhost")
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
204 (if (getenv "MPD_PORT") (concat ":" (getenv "MPD_PORT"))))
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
205 "Host (and port) where the Music Player Daemon is running.
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
206 The format is \"HOST\" or \"HOST:PORT\" where PORT defaults to 6600
|
106365
|
207 and HOST defaults to localhost."
|
106342
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
208 :type 'string)
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
209
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
210 (defvar mpc-proc nil)
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
211
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
212 (defconst mpc--proc-end-re "^\\(?:OK\\(?: MPD .*\\)?\\|ACK \\(.*\\)\\)\n")
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
213
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
214 (put 'mpc-proc-error 'error-conditions '(mpc-proc-error error))
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
215 (put 'mpc-proc-error 'error-message "MPD error")
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
216
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
217 (defun mpc--debug (format &rest args)
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
218 (if (get-buffer "*MPC-debug*")
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
219 (with-current-buffer "*MPC-debug*"
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
220 (goto-char (point-max))
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
221 (insert-before-markers ;So it scrolls.
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
222 (replace-regexp-in-string "\n" "\n "
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
223 (apply 'format format args))
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
224 "\n"))))
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
225
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
226 (defun mpc--proc-filter (proc string)
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
227 (mpc--debug "Receive \"%s\"" string)
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
228 (with-current-buffer (process-buffer proc)
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
229 (if (process-get proc 'ready)
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
230 (if nil ;; (string-match "\\`\\(OK\n\\)+\\'" string)
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
231 ;; I haven't figured out yet why I get those extraneous OKs,
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
232 ;; so I'll just ignore them for now.
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
233 nil
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
234 (delete-process proc)
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
235 (set-process-buffer proc nil)
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
236 (pop-to-buffer (clone-buffer))
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
237 (error "MPD output while idle!?"))
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
238 (save-excursion
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
239 (let ((start (or (marker-position (process-mark proc)) (point-min))))
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
240 (goto-char start)
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
241 (insert string)
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
242 (move-marker (process-mark proc) (point))
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
243 (beginning-of-line)
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
244 (when (and (< start (point))
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
245 (re-search-backward mpc--proc-end-re start t))
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
246 (process-put proc 'ready t)
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
247 (unless (eq (match-end 0) (point-max))
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
248 (error "Unexpected trailing text"))
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
249 (let ((error (match-string 1)))
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
250 (delete-region (point) (point-max))
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
251 (let ((callback (process-get proc 'callback)))
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
252 (process-put proc 'callback nil)
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
253 (if error (signal 'mpc-proc-error error))
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
254 (funcall callback)))))))))
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
255
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
256 (defun mpc--proc-connect (host)
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
257 (mpc--debug "Connecting to %s..." host)
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
258 (with-current-buffer (get-buffer-create (format " *mpc-%s*" host))
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
259 ;; (pop-to-buffer (current-buffer))
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
260 (let (proc)
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
261 (while (and (setq proc (get-buffer-process (current-buffer)))
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
262 (progn ;; (debug)
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
263 (delete-process proc)))))
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
264 (erase-buffer)
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
265 (let ((port 6600))
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
266 (when (string-match ":[^.]+\\'" host)
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
267 (setq port (substring host (1+ (match-beginning 0))))
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
268 (setq host (substring host 0 (match-beginning 0)))
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
269 (unless (string-match "[^[:digit:]]" port)
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
270 (setq port (string-to-number port))))
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
271 (let* ((coding-system-for-read 'utf-8-unix)
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
272 (coding-system-for-write 'utf-8-unix)
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
273 (proc (open-network-stream "MPC" (current-buffer) host port)))
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
274 (when (processp mpc-proc)
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
275 ;; Inherit the properties of the previous connection.
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
276 (let ((plist (process-plist mpc-proc)))
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
277 (while plist (process-put proc (pop plist) (pop plist)))))
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
278 (mpc-proc-buffer proc 'mpd-commands (current-buffer))
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
279 (process-put proc 'callback 'ignore)
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
280 (process-put proc 'ready nil)
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
281 (clrhash mpc--find-memoize)
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
282 (set-process-filter proc 'mpc--proc-filter)
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
283 (set-process-sentinel proc 'ignore)
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
284 (set-process-query-on-exit-flag proc nil)
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
285 ;; This may be called within a process filter ;-(
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
286 (with-local-quit (mpc-proc-sync proc))
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
287 proc))))
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
288
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
289 (defun mpc--proc-quote-string (s)
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
290 (if (numberp s) (number-to-string s)
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
291 (setq s (replace-regexp-in-string "[\"\\]" "\\\\\\&" s))
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
292 (if (string-match " " s) (concat "\"" s "\"") s)))
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
293
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
294 (defconst mpc--proc-alist-to-alists-starters '(file directory))
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
295
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
296 (defun mpc--proc-alist-to-alists (alist)
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
297 (assert (or (null alist)
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
298 (memq (caar alist) mpc--proc-alist-to-alists-starters)))
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
299 (let ((starter (caar alist))
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
300 (alists ())
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
301 tmp)
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
302 (dolist (pair alist)
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
303 (when (eq (car pair) starter)
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
304 (if tmp (push (nreverse tmp) alists))
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
305 (setq tmp ()))
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
306 (push pair tmp))
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
307 (if tmp (push (nreverse tmp) alists))
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
308 (nreverse alists)))
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
309
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
310 (defun mpc-proc ()
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
311 (or (and mpc-proc
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
312 (buffer-live-p (process-buffer mpc-proc))
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
313 (not (memq (process-status mpc-proc) '(closed)))
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
314 mpc-proc)
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
315 (setq mpc-proc (mpc--proc-connect mpc-host))))
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
316
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
317 (defun mpc-proc-sync (&optional proc)
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
318 "Wait for MPC process until it is idle again.
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
319 Return the buffer in which the process is/was running."
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
320 (unless proc (setq proc (mpc-proc)))
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
321 (unwind-protect
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
322 (condition-case err
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
323 (progn
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
324 (while (and (not (process-get proc 'ready))
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
325 (accept-process-output proc)))
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
326 (if (process-get proc 'ready) (process-buffer proc)
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
327 ;; (delete-process proc)
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
328 (error "No response from MPD")))
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
329 (error (message "MPC: %s" err) (signal (car err) (cdr err))))
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
330 (unless (process-get proc 'ready)
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
331 ;; (debug)
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
332 (message "Killing hung process")
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
333 (delete-process proc))))
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
334
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
335 (defun mpc-proc-cmd (cmd &optional callback)
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
336 "Send command CMD to the MPD server.
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
337 If CALLBACK is nil, wait for the command to finish before returning,
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
338 otherwise return immediately and call CALLBACK with no argument
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
339 when the command terminates.
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
340 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
|
341 which will be concatenated with proper quoting before passing them to MPD."
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
342 (let ((proc (mpc-proc)))
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
343 (if (and callback (not (process-get proc 'ready)))
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
344 (lexical-let ((old (process-get proc 'callback))
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
345 (callback callback)
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
346 (cmd cmd))
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
347 (process-put proc 'callback
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
348 (lambda ()
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
349 (funcall old)
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
350 (mpc-proc-cmd cmd callback))))
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
351 ;; Wait for any pending async command to terminate.
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
352 (mpc-proc-sync proc)
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
353 (process-put proc 'ready nil)
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
354 (with-current-buffer (process-buffer proc)
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
355 (erase-buffer)
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
356 (mpc--debug "Send \"%s\"" cmd)
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
357 (process-send-string
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
358 proc (concat (if (stringp cmd) cmd
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
359 (mapconcat 'mpc--proc-quote-string cmd " "))
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
360 "\n")))
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
361 (if callback
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
362 (lexical-let ((buf (current-buffer))
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
363 (callback callback))
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
364 (process-put proc 'callback
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
365 callback
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
366 ;; (lambda ()
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
367 ;; (funcall callback
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
368 ;; (prog1 (current-buffer)
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
369 ;; (set-buffer buf))))
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
370 ))
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
371 ;; If `callback' is nil, we're executing synchronously.
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
372 (process-put proc 'callback 'ignore)
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
373 ;; This returns the process's buffer.
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
374 (mpc-proc-sync proc)))))
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
375
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
376 ;; This function doesn't exist in Emacs-21.
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
377 ;; (put 'mpc-proc-cmd-list 'byte-optimizer 'byte-optimize-pure-func)
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
378 (defun mpc-proc-cmd-list (cmds)
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
379 (concat "command_list_begin\n"
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
380 (mapconcat (lambda (cmd)
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
381 (if (stringp cmd) cmd
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
382 (mapconcat 'mpc--proc-quote-string cmd " ")))
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
383 cmds
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
384 "\n")
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
385 "\ncommand_list_end"))
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
386
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
387 (defun mpc-proc-cmd-list-ok ()
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
388 ;; To implement this, we'll need to tweak the process filter since we'd
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
389 ;; then sometimes get "trailing" text after "OK\n".
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
390 (error "Not implemented yet"))
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
391
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
392 (defun mpc-proc-buf-to-alist (&optional buf)
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
393 (with-current-buffer (or buf (current-buffer))
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
394 (let ((res ()))
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
395 (goto-char (point-min))
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
396 (while (re-search-forward "^\\([^:]+\\): \\(.*\\)\n" nil t)
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
397 (push (cons (intern (match-string 1)) (match-string 2)) res))
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
398 (nreverse res))))
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
399
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
400 (defun mpc-proc-buf-to-alists (buf)
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
401 (mpc--proc-alist-to-alists (mpc-proc-buf-to-alist buf)))
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
402
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
403 (defun mpc-proc-cmd-to-alist (cmd &optional callback)
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
404 (if callback
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
405 (lexical-let ((buf (current-buffer))
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
406 (callback callback))
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
407 (mpc-proc-cmd cmd (lambda ()
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
408 (funcall callback (prog1 (mpc-proc-buf-to-alist
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
409 (current-buffer))
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
410 (set-buffer buf))))))
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
411 ;; (lexical-let ((res nil))
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
412 ;; (mpc-proc-cmd-to-alist cmd (lambda (alist) (setq res alist)))
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
413 ;; (mpc-proc-sync)
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
414 ;; res)
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
415 (mpc-proc-buf-to-alist (mpc-proc-cmd cmd))))
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
416
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
417 (defun mpc-proc-tag-string-to-sym (tag)
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
418 (intern (capitalize tag)))
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
419
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
420 (defun mpc-proc-buffer (proc use &optional buffer)
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
421 (let* ((bufs (process-get proc 'buffers))
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
422 (buf (cdr (assoc use bufs))))
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
423 (cond
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
424 ((and buffer (buffer-live-p buf) (not (eq buffer buf)))
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
425 (error "Duplicate MPC buffer for %s" use))
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
426 (buffer
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
427 (if buf
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
428 (setcdr (assoc use bufs) buffer)
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
429 (process-put proc 'buffers (cons (cons use buffer) bufs))))
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
430 (t buf))))
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
431
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
432 ;;; Support for regularly updated current status information ;;;;;;;;;;;;;;;
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
433
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
434 ;; Exported elements:
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
435 ;; `mpc-status' holds the uptodate data.
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
436 ;; `mpc-status-callbacks' holds the registered callback functions.
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
437 ;; `mpc-status-refresh' forces a refresh of the data.
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
438 ;; `mpc-status-stop' stops the automatic updating.
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
439
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
440 (defvar mpc-status nil)
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
441 (defvar mpc-status-callbacks
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
442 '((state . mpc--status-timers-refresh)
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
443 ;; (song . mpc--queue-refresh)
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
444 ;; (state . mpc--queue-refresh) ;To detect the end of the last song.
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
445 (state . mpc--faster-toggle-refresh) ;Only ffwd/rewind while play/pause.
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
446 (volume . mpc-volume-refresh)
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
447 (file . mpc-songpointer-refresh)
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
448 ;; The song pointer may need updating even if the file doesn't change,
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
449 ;; if the same song appears multiple times in a row.
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
450 (song . mpc-songpointer-refresh)
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
451 (updating_db . mpc-updated-db)
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
452 (updating_db . mpc--status-timers-refresh)
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
453 (t . mpc-current-refresh))
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
454 "Alist associating properties to the functions that care about them.
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
455 Each entry has the form (PROP . FUN) where PROP can be t to mean
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
456 to call FUN for any change whatsoever.")
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
457
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
458 (defun mpc--status-callback ()
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
459 (let ((old-status mpc-status))
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
460 ;; Update the alist.
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
461 (setq mpc-status (mpc-proc-buf-to-alist))
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
462 (assert mpc-status)
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
463 (unless (equal old-status mpc-status)
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
464 ;; Run the relevant refresher functions.
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
465 (dolist (pair mpc-status-callbacks)
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
466 (when (or (eq t (car pair))
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
467 (not (equal (cdr (assq (car pair) old-status))
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
468 (cdr (assq (car pair) mpc-status)))))
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
469 (funcall (cdr pair)))))))
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
470
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
471 (defvar mpc--status-timer nil)
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
472 (defun mpc--status-timer-start ()
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
473 (add-hook 'pre-command-hook 'mpc--status-timer-stop)
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
474 (unless mpc--status-timer
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
475 (setq mpc--status-timer (run-with-timer 1 1 'mpc--status-timer-run))))
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
476 (defun mpc--status-timer-stop ()
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
477 (when mpc--status-timer
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
478 (cancel-timer mpc--status-timer)
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
479 (setq mpc--status-timer nil)))
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
480 (defun mpc--status-timer-run ()
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
481 (when (process-get (mpc-proc) 'ready)
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
482 (condition-case err
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
483 (with-local-quit (mpc-status-refresh))
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
484 (error (message "MPC: %s" err)))))
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
485
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
486 (defvar mpc--status-idle-timer nil)
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
487 (defun mpc--status-idle-timer-start ()
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
488 (when mpc--status-idle-timer
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
489 ;; 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
|
490 (cancel-timer mpc--status-idle-timer))
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
491 (setq mpc--status-idle-timer
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
492 (run-with-idle-timer 1 t 'mpc--status-idle-timer-run))
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
493 ;; Typically, the idle timer is started from the mpc--status-callback,
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
494 ;; which is run asynchronously while we're already idle (we typically
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
495 ;; just started idling), so the timer itself will only be run the next
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
496 ;; time we idle :-(
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
497 ;; To work around that, we immediately start the repeat timer.
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
498 (mpc--status-timer-start))
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
499 (defun mpc--status-idle-timer-stop (&optional really)
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
500 (when mpc--status-idle-timer
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
501 ;; 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
|
502 (cancel-timer mpc--status-idle-timer))
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
503 (setq mpc--status-idle-timer
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
504 (unless really
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
505 ;; We don't completely stop the timer, so that if some other MPD
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
506 ;; client starts playback, we may get a chance to notice it.
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
507 (run-with-idle-timer 10 t 'mpc--status-idle-timer-run))))
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
508 (defun mpc--status-idle-timer-run ()
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
509 (when (process-get (mpc-proc) 'ready)
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
510 (condition-case err
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
511 (with-local-quit (mpc-status-refresh))
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
512 (error (message "MPC: %s" err))))
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
513 (mpc--status-timer-start))
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
514
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
515 (defun mpc--status-timers-refresh ()
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
516 "Start/stop the timers according to whether a song is playing."
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
517 (if (or (member (cdr (assq 'state mpc-status)) '("play"))
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
518 (cdr (assq 'updating_db mpc-status)))
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
519 (mpc--status-idle-timer-start)
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
520 (mpc--status-idle-timer-stop)
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
521 (mpc--status-timer-stop)))
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
522
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
523 (defun mpc-status-refresh (&optional callback)
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
524 "Refresh `mpc-status'."
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
525 (lexical-let ((cb callback))
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
526 (mpc-proc-cmd (mpc-proc-cmd-list '("status" "currentsong"))
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
527 (lambda ()
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
528 (mpc--status-callback)
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
529 (if cb (funcall cb))))))
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
530
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
531 (defun mpc-status-stop ()
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
532 "Stop the autorefresh of `mpc-status'.
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
533 This is normally used only when quitting MPC.
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
534 Any call to `mpc-status-refresh' may cause it to be restarted."
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
535 (setq mpc-status nil)
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
536 (mpc--status-idle-timer-stop 'really)
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
537 (mpc--status-timer-stop))
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
538
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
539 ;;; A thin layer above the raw protocol commands ;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
540
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
541 ;; (defvar mpc-queue nil)
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
542 ;; (defvar mpc-queue-back nil)
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
543
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
544 ;; (defun mpc--queue-head ()
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
545 ;; (if (stringp (car mpc-queue)) (car mpc-queue) (cadar mpc-queue)))
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
546 ;; (defun mpc--queue-pop ()
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
547 ;; (when mpc-queue ;Can be nil if out of sync.
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
548 ;; (let ((song (car mpc-queue)))
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
549 ;; (assert song)
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
550 ;; (push (if (and (consp song) (cddr song))
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
551 ;; ;; The queue's first element is itself a list of
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
552 ;; ;; songs, where the first element isn't itself a song
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
553 ;; ;; but a description of the list.
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
554 ;; (prog1 (cadr song) (setcdr song (cddr song)))
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
555 ;; (prog1 (if (consp song) (cadr song) song)
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
556 ;; (setq mpc-queue (cdr mpc-queue))))
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
557 ;; mpc-queue-back)
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
558 ;; (assert (stringp (car mpc-queue-back))))))
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
559
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
560 ;; (defun mpc--queue-refresh ()
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
561 ;; ;; Maintain the queue.
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
562 ;; (mpc--debug "mpc--queue-refresh")
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
563 ;; (let ((pos (cdr (or (assq 'Pos mpc-status) (assq 'song mpc-status)))))
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
564 ;; (cond
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
565 ;; ((null pos)
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
566 ;; (mpc-cmd-clear 'ignore))
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
567 ;; ((or (not (member pos '("0" nil)))
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
568 ;; ;; There's only one song in the playlist and we've stopped.
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
569 ;; ;; Maybe it's because of some external client that set the
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
570 ;; ;; playlist like that and/or manually stopped the playback, but
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
571 ;; ;; it's more likely that we've simply reached the end of
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
572 ;; ;; the song. So remove it.
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
573 ;; (and (equal (assq 'state mpc-status) "stop")
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
574 ;; (equal (assq 'playlistlength mpc-status) "1")
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
575 ;; (setq pos "1")))
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
576 ;; ;; We're not playing the first song in the queue/playlist any
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
577 ;; ;; more, so update the queue.
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
578 ;; (dotimes (i (string-to-number pos)) (mpc--queue-pop))
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
579 ;; (mpc-proc-cmd (mpc-proc-cmd-list
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
580 ;; (make-list (string-to-number pos) "delete 0"))
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
581 ;; 'ignore)
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
582 ;; (if (not (equal (cdr (assq 'file mpc-status))
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
583 ;; (mpc--queue-head)))
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
584 ;; (message "MPC's queue is out of sync"))))))
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
585
|
107541
|
586 (defvar mpc--find-memoize-union-tags nil)
|
|
587
|
|
588 (defun mpc-cmd-flush (tag value)
|
|
589 (puthash (cons tag value) nil mpc--find-memoize)
|
|
590 (dolist (uniontag mpc--find-memoize-union-tags)
|
|
591 (if (member (symbol-name tag) (split-string (symbol-name uniontag) "|"))
|
|
592 (puthash (cons uniontag value) nil mpc--find-memoize))))
|
|
593
|
|
594
|
|
595 (defun mpc-cmd-special-tag-p (tag)
|
|
596 (or (memq tag '(Playlist Search Directory))
|
|
597 (string-match "|" (symbol-name tag))))
|
|
598
|
106342
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
599 (defun mpc-cmd-find (tag value)
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
600 "Return a list of all songs whose tag TAG has value VALUE.
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
601 The songs are returned as alists."
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
602 (or (gethash (cons tag value) mpc--find-memoize)
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
603 (puthash (cons tag value)
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
604 (cond
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
605 ((eq tag 'Playlist)
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
606 ;; Special case for pseudo-tag playlist.
|
107541
|
607 (let ((l (condition-case err
|
|
608 (mpc-proc-buf-to-alists
|
|
609 (mpc-proc-cmd (list "listplaylistinfo" value)))
|
|
610 (mpc-proc-error
|
|
611 ;; "[50@0] {listplaylistinfo} No such playlist"
|
|
612 nil)))
|
106342
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
613 (i 0))
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
614 (mapcar (lambda (s)
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
615 (prog1 (cons (cons 'Pos (number-to-string i)) s)
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
616 (incf i)))
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
617 l)))
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
618 ((eq tag 'Search)
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
619 (mpc-proc-buf-to-alists
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
620 (mpc-proc-cmd (list "search" "any" value))))
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
621 ((eq tag 'Directory)
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
622 (let ((pairs
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
623 (mpc-proc-buf-to-alist
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
624 (mpc-proc-cmd (list "listallinfo" value)))))
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
625 (mpc--proc-alist-to-alists
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
626 ;; Strip away the `directory' entries.
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
627 (delq nil (mapcar (lambda (pair)
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
628 (if (eq (car pair) 'directory)
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
629 nil pair))
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
630 pairs)))))
|
107541
|
631 ((string-match "|" (symbol-name tag))
|
|
632 (add-to-list 'mpc--find-memoize-union-tags tag)
|
|
633 (let ((tag1 (intern (substring (symbol-name tag)
|
|
634 0 (match-beginning 0))))
|
|
635 (tag2 (intern (substring (symbol-name tag)
|
|
636 (match-end 0)))))
|
|
637 (mpc-union (mpc-cmd-find tag1 value)
|
|
638 (mpc-cmd-find tag2 value))))
|
106342
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
639 (t
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
640 (condition-case err
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
641 (mpc-proc-buf-to-alists
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
642 (mpc-proc-cmd (list "find" (symbol-name tag) value)))
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
643 (mpc-proc-error
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
644 ;; If `tag' is not one of the expected tags, MPD burps
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
645 ;; about not having the relevant table. FIXME: check
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
646 ;; the kind of error.
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
647 (error "Unknown tag %s" tag)
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
648 (let ((res ()))
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
649 (setq value (cons tag value))
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
650 (dolist (song (mpc-proc-buf-to-alists
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
651 (mpc-proc-cmd "listallinfo")))
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
652 (if (member value song) (push song res)))
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
653 res)))))
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
654 mpc--find-memoize)))
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
655
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
656 (defun mpc-cmd-list (tag &optional other-tag value)
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
657 ;; FIXME: we could also provide a `mpc-cmd-list' alternative which
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
658 ;; doesn't take an "other-tag value" constraint but a "song-list" instead.
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
659 ;; That might be more efficient in some cases.
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
660 (cond
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
661 ((eq tag 'Playlist)
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
662 (let ((pls (mpc-assq-all 'playlist (mpc-proc-cmd-to-alist "lsinfo"))))
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
663 (when other-tag
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
664 (dolist (pl (prog1 pls (setq pls nil)))
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
665 (let ((plsongs (mpc-cmd-find 'Playlist pl)))
|
107541
|
666 (if (not (mpc-cmd-special-tag-p other-tag))
|
106342
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
667 (when (member (cons other-tag value)
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
668 (apply 'append plsongs))
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
669 (push pl pls))
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
670 ;; Problem N°2: we compute the intersection whereas all
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
671 ;; we care about is whether it's empty. So we could
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
672 ;; speed this up significantly.
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
673 ;; We only compare file names, because the full song-entries
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
674 ;; are slightly different (the ones in plsongs include
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
675 ;; position and id info specific to the playlist), and it's
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
676 ;; good enough because this is only used with "search", which
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
677 ;; doesn't pay attention to playlists and URLs anyway.
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
678 (let* ((osongs (mpc-cmd-find other-tag value))
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
679 (ofiles (mpc-assq-all 'file (apply 'append osongs)))
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
680 (plfiles (mpc-assq-all 'file (apply 'append plsongs))))
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
681 (when (mpc-intersection plfiles ofiles)
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
682 (push pl pls)))))))
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
683 pls))
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
684
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
685 ((eq tag 'Directory)
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
686 (if (null other-tag)
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
687 (apply 'nconc
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
688 (mpc-assq-all 'directory
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
689 (mpc-proc-buf-to-alist
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
690 (mpc-proc-cmd "lsinfo")))
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
691 (mapcar (lambda (dir)
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
692 (let ((shortdir
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
693 (if (get-text-property 0 'display dir)
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
694 (concat " "
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
695 (get-text-property 0 'display dir))
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
696 " ↪ "))
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
697 (subdirs
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
698 (mpc-assq-all 'directory
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
699 (mpc-proc-buf-to-alist
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
700 (mpc-proc-cmd (list "lsinfo" dir))))))
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
701 (dolist (subdir subdirs)
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
702 (put-text-property 0 (1+ (length dir))
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
703 'display shortdir
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
704 subdir))
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
705 subdirs))
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
706 (process-get (mpc-proc) 'Directory)))
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
707 ;; If there's an other-tag, then just extract the dir info from the
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
708 ;; list of other-tag's songs.
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
709 (let* ((other-songs (mpc-cmd-find other-tag value))
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
710 (files (mpc-assq-all 'file (apply 'append other-songs)))
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
711 (dirs '()))
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
712 (dolist (file files)
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
713 (let ((dir (file-name-directory file)))
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
714 (if (and dir (setq dir (directory-file-name dir))
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
715 (not (equal dir (car dirs))))
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
716 (push dir dirs))))
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
717 ;; Dirs might have duplicates still.
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
718 (setq dirs (delete-dups dirs))
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
719 (let ((newdirs dirs))
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
720 (while newdirs
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
721 (let ((dir (file-name-directory (pop newdirs))))
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
722 (when (and dir (setq dir (directory-file-name dir))
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
723 (not (member dir dirs)))
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
724 (push dir newdirs)
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
725 (push dir dirs)))))
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
726 dirs)))
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
727
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
728 ;; The UI should not provide access to such a thing anyway currently.
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
729 ;; But I could imagine adding in the future a browser for the "search"
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
730 ;; tag, which would provide things like previous searches. Not sure how
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
731 ;; useful that would be tho.
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
732 ((eq tag 'Search) (error "Not supported"))
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
733
|
107541
|
734 ((string-match "|" (symbol-name tag))
|
|
735 (let ((tag1 (intern (substring (symbol-name tag)
|
|
736 0 (match-beginning 0))))
|
|
737 (tag2 (intern (substring (symbol-name tag)
|
|
738 (match-end 0)))))
|
|
739 (mpc-union (mpc-cmd-list tag1 other-tag value)
|
|
740 (mpc-cmd-list tag2 other-tag value))))
|
|
741
|
106342
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
742 ((null other-tag)
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
743 (condition-case nil
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
744 (mapcar 'cdr (mpc-proc-cmd-to-alist (list "list" (symbol-name tag))))
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
745 (mpc-proc-error
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
746 ;; If `tag' is not one of the expected tags, MPD burps about not
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
747 ;; having the relevant table.
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
748 ;; FIXME: check the kind of error.
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
749 (error "MPD does not know this tag %s" tag)
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
750 (mpc-assq-all tag (mpc-proc-cmd-to-alist "listallinfo")))))
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
751 (t
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
752 (condition-case nil
|
107541
|
753 (if (mpc-cmd-special-tag-p other-tag)
|
106342
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
754 (signal 'mpc-proc-error "Not implemented")
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
755 (mapcar 'cdr
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
756 (mpc-proc-cmd-to-alist
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
757 (list "list" (symbol-name tag)
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
758 (symbol-name other-tag) value))))
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
759 (mpc-proc-error
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
760 ;; DAMN!! the 3-arg form of `list' is new in 0.12 !!
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
761 ;; FIXME: check the kind of error.
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
762 (let ((other-songs (mpc-cmd-find other-tag value)))
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
763 (mpc-assq-all tag
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
764 ;; Don't use `nconc' now that mpc-cmd-find may
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
765 ;; return a memoized result.
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
766 (apply 'append other-songs))))))))
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
767
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
768 (defun mpc-cmd-stop (&optional callback)
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
769 (mpc-proc-cmd "stop" callback))
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
770
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
771 (defun mpc-cmd-clear (&optional callback)
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
772 (mpc-proc-cmd "clear" callback)
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
773 ;; (setq mpc-queue-back nil mpc-queue nil)
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
774 )
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
775
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
776 (defun mpc-cmd-pause (&optional arg callback)
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
777 "Pause or resume playback of the queue of songs."
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
778 (lexical-let ((cb callback))
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
779 (mpc-proc-cmd (list "pause" arg)
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
780 (lambda () (mpc-status-refresh) (if cb (funcall cb))))
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
781 (unless callback (mpc-proc-sync))))
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
782
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
783 (defun mpc-cmd-status ()
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
784 (mpc-proc-cmd-to-alist "status"))
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
785
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
786 (defun mpc-cmd-play ()
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
787 (mpc-proc-cmd "play")
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
788 (mpc-status-refresh))
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
789
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
790 (defun mpc-cmd-add (files &optional playlist)
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
791 "Add the songs FILES to PLAYLIST.
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
792 If PLAYLIST is t or nil or missing, use the main playlist."
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
793 (mpc-proc-cmd (mpc-proc-cmd-list
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
794 (mapcar (lambda (file)
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
795 (if (stringp playlist)
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
796 (list "playlistadd" playlist file)
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
797 (list "add" file)))
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
798 files)))
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
799 (if (stringp playlist)
|
107541
|
800 (mpc-cmd-flush 'Playlist playlist)))
|
106342
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
801
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
802 (defun mpc-cmd-delete (song-poss &optional playlist)
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
803 "Delete the songs at positions SONG-POSS from PLAYLIST.
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
804 If PLAYLIST is t or nil or missing, use the main playlist."
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
805 (mpc-proc-cmd (mpc-proc-cmd-list
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
806 (mapcar (lambda (song-pos)
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
807 (if (stringp playlist)
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
808 (list "playlistdelete" playlist song-pos)
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
809 (list "delete" song-pos)))
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
810 ;; Sort them from last to first, so the renumbering
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
811 ;; caused by the earlier deletions don't affect
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
812 ;; later ones.
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
813 (sort song-poss '>))))
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
814 (if (stringp playlist)
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
815 (puthash (cons 'Playlist playlist) nil mpc--find-memoize)))
|
106354
|
816
|
106342
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
817
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
818 (defun mpc-cmd-move (song-poss dest-pos &optional playlist)
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
819 (let ((i 0))
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
820 (mpc-proc-cmd
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
821 (mpc-proc-cmd-list
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
822 (mapcar (lambda (song-pos)
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
823 (if (>= song-pos dest-pos)
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
824 ;; positions past dest-pos have been
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
825 ;; shifted by i.
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
826 (setq song-pos (+ song-pos i)))
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
827 (prog1 (if (stringp playlist)
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
828 (list "playlistmove" playlist song-pos dest-pos)
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
829 (list "move" song-pos dest-pos))
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
830 (if (< song-pos dest-pos)
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
831 ;; This move has shifted dest-pos by 1.
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
832 (decf dest-pos))
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
833 (incf i)))
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
834 ;; Sort them from last to first, so the renumbering
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
835 ;; caused by the earlier deletions affect
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
836 ;; later ones a bit less.
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
837 (sort song-poss '>))))
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
838 (if (stringp playlist)
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
839 (puthash (cons 'Playlist playlist) nil mpc--find-memoize))))
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
840
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
841 (defun mpc-cmd-update (&optional arg callback)
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
842 (lexical-let ((cb callback))
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
843 (mpc-proc-cmd (if arg (list "update" arg) "update")
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
844 (lambda () (mpc-status-refresh) (if cb (funcall cb))))
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
845 (unless callback (mpc-proc-sync))))
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
846
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
847 (defun mpc-cmd-tagtypes ()
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
848 (mapcar 'cdr (mpc-proc-cmd-to-alist "tagtypes")))
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
849
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
850 ;; This was never integrated into MPD.
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
851 ;; (defun mpc-cmd-download (file)
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
852 ;; (with-current-buffer (generate-new-buffer " *mpc download*")
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
853 ;; (set-buffer-multibyte nil)
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
854 ;; (let* ((proc (mpc-proc))
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
855 ;; (stdbuf (process-buffer proc))
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
856 ;; (markpos (marker-position (process-mark proc)))
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
857 ;; (stdcoding (process-coding-system proc)))
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
858 ;; (unwind-protect
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
859 ;; (progn
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
860 ;; (set-process-buffer proc (current-buffer))
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
861 ;; (set-process-coding-system proc 'binary (cdr stdcoding))
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
862 ;; (set-marker (process-mark proc) (point))
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
863 ;; (mpc-proc-cmd (list "download" file)))
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
864 ;; (set-process-buffer proc stdbuf)
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
865 ;; (set-marker (process-mark proc) markpos stdbuf)
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
866 ;; (set-process-coding-system proc (car stdcoding) (cdr stdcoding)))
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
867 ;; ;; The command has completed, let's decode.
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
868 ;; (goto-char (point-max))
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
869 ;; (delete-char -1) ;Delete final newline.
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
870 ;; (while (re-search-backward "^>" nil t)
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
871 ;; (delete-char 1))
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
872 ;; (current-buffer))))
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
873
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
874 ;;; Misc ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
875
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
876 (defcustom mpc-mpd-music-directory nil
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
877 "Location of MPD's music directory."
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
878 :type '(choice (const nil) directory))
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
879
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
880 (defcustom mpc-data-directory
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
881 (if (and (not (file-directory-p "~/.mpc"))
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
882 (file-directory-p "~/.emacs.d"))
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
883 "~/.emacs.d/mpc" "~/.mpc")
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
884 "Directory where MPC.el stores auxiliary data."
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
885 :type 'directory)
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
886
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
887 (defun mpc-data-directory ()
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
888 (unless (file-directory-p mpc-data-directory)
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
889 (make-directory mpc-data-directory))
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
890 mpc-data-directory)
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
891
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
892 (defun mpc-file-local-copy (file)
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
893 ;; Try to set mpc-mpd-music-directory.
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
894 (when (and (null mpc-mpd-music-directory)
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
895 (string-match "\\`localhost" mpc-host))
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
896 (let ((files '("~/.mpdconf" "/etc/mpd.conf"))
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
897 file)
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
898 (while (and files (not file))
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
899 (if (file-exists-p (car files)) (setq file (car files)))
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
900 (setq files (cdr files)))
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
901 (with-temp-buffer
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
902 (ignore-errors (insert-file-contents file))
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
903 (goto-char (point-min))
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
904 (if (re-search-forward "^music_directory[ ]+\"\\([^\"]+\\)\"")
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
905 (setq mpc-mpd-music-directory
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
906 (match-string 1))))))
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
907 ;; Use mpc-mpd-music-directory if applicable, or else try to use the
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
908 ;; `download' command, although it's never been accepted in `mpd' :-(
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
909 (if (and mpc-mpd-music-directory
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
910 (file-exists-p (expand-file-name file mpc-mpd-music-directory)))
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
911 (expand-file-name file mpc-mpd-music-directory)
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
912 ;; (let ((aux (expand-file-name (replace-regexp-in-string "[/]" "|" file)
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
913 ;; (mpc-data-directory))))
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
914 ;; (unless (file-exists-p aux)
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
915 ;; (condition-case err
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
916 ;; (with-local-quit
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
917 ;; (with-current-buffer (mpc-cmd-download file)
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
918 ;; (write-region (point-min) (point-max) aux)
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
919 ;; (kill-buffer (current-buffer))))
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
920 ;; (mpc-proc-error (message "Download error: %s" err) (setq aux nil))))
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
921 ;; aux)
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
922 ))
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
923
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
924 ;;; Formatter ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
925
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
926 (defun mpc-secs-to-time (secs)
|
107541
|
927 ;; We could use `format-seconds', but it doesn't seem worth the trouble
|
|
928 ;; because we'd still need to check (>= secs (* 60 100)) since the special
|
|
929 ;; %z only allows us to drop the large units for small values but
|
|
930 ;; not to drop the small units for large values.
|
106342
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
|
107541
|
1435 (defun mpc-tagbrowser-tag-name (tag)
|
|
1436 (cond
|
|
1437 ((string-match "|" (symbol-name tag))
|
|
1438 (let ((tag1 (intern (substring (symbol-name tag)
|
|
1439 0 (match-beginning 0))))
|
|
1440 (tag2 (intern (substring (symbol-name tag)
|
|
1441 (match-end 0)))))
|
|
1442 (concat (mpc-tagbrowser-tag-name tag1)
|
|
1443 " | "
|
|
1444 (mpc-tagbrowser-tag-name tag2))))
|
|
1445 ((string-match "y\\'" (symbol-name tag))
|
|
1446 (concat (substring (symbol-name tag) 0 -1) "ies"))
|
|
1447 (t (concat (symbol-name tag) "s"))))
|
|
1448
|
106342
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
1449 (defun mpc-tagbrowser-buf (tag)
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
1450 (let ((buf (mpc-proc-buffer (mpc-proc) tag)))
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
1451 (if (buffer-live-p buf) buf
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
1452 (setq buf (get-buffer-create (format "*MPC %ss*" tag)))
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
1453 (mpc-proc-buffer (mpc-proc) tag buf)
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
1454 (with-current-buffer buf
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
1455 (let ((inhibit-read-only t))
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
1456 (erase-buffer)
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
1457 (if (member tag '(Directory))
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
1458 (mpc-tagbrowser-dir-mode)
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
1459 (mpc-tagbrowser-mode))
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
1460 (insert mpc-tagbrowser-all-name "\n"))
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
1461 (forward-line -1)
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
1462 (setq mpc-tag tag)
|
107541
|
1463 (setq mpc-tag-name (mpc-tagbrowser-tag-name tag))
|
106342
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
1464 (mpc-tagbrowser-all-select)
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
1465 (mpc-tagbrowser-refresh)
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
1466 buf))))
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
1467
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
1468 (defvar tag-browser-tagtypes
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
1469 (lazy-completion-table tag-browser-tagtypes
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
1470 (lambda ()
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
1471 (append '("Playlist" "Directory")
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
1472 (mpc-cmd-tagtypes)))))
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
1473
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
1474 (defun mpc-tagbrowser (tag)
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
1475 "Create a new browser for TAG."
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
1476 (interactive
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
1477 (list
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
1478 (let ((completion-ignore-case t))
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
1479 (intern
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
1480 (completing-read "Tag: " tag-browser-tagtypes nil 'require-match)))))
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
1481 (let* ((newbuf (mpc-tagbrowser-buf tag))
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
1482 (win (get-buffer-window newbuf 0)))
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
1483 (if win (select-window win)
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
1484 (if (with-current-buffer (window-buffer (selected-window))
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
1485 (derived-mode-p 'mpc-tagbrowser-mode))
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
1486 (setq win (selected-window))
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
1487 ;; Find a tagbrowser-mode buffer.
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
1488 (let ((buffers (process-get (mpc-proc) 'buffers))
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
1489 buffer)
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
1490 (while
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
1491 (and buffers
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
1492 (not (and (buffer-live-p (setq buffer (cdr (pop buffers))))
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
1493 (with-current-buffer buffer
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
1494 (derived-mode-p 'mpc-tagbrowser-mode))
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
1495 (setq win (get-buffer-window buffer 0))))))))
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
1496 (if (not win)
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
1497 (pop-to-buffer newbuf)
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
1498 (setq win (split-window win nil 'horiz))
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
1499 (set-window-buffer win newbuf)
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
1500 (set-window-dedicated-p win 'soft)
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
1501 (select-window win)
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
1502 (balance-windows-area)))))
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
1503
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
1504 (defun mpc-tagbrowser-all-select ()
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
1505 "Select the special *ALL* entry if no other is selected."
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
1506 (if mpc-select
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
1507 (delete-overlay mpc-tagbrowser-all-ol)
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
1508 (save-excursion
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
1509 (goto-char (point-min))
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
1510 (if mpc-tagbrowser-all-ol
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
1511 (move-overlay mpc-tagbrowser-all-ol
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
1512 (point) (line-beginning-position 2))
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
1513 (let ((ol (make-overlay (point) (line-beginning-position 2))))
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
1514 (overlay-put ol 'face 'region)
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
1515 (overlay-put ol 'evaporate t)
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
1516 (set (make-local-variable 'mpc-tagbrowser-all-ol) ol))))))
|
106354
|
1517
|
106342
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
1518 ;; (defvar mpc-constraints nil)
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
1519 (defun mpc-separator (active)
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
1520 ;; Place a separator mark.
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
1521 (unless mpc-separator-ol
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
1522 (set (make-local-variable 'mpc-separator-ol)
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
1523 (make-overlay (point) (point)))
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
1524 (overlay-put mpc-separator-ol 'after-string
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
1525 (propertize "\n"
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
1526 'face '(:height 0.05 :inverse-video t))))
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
1527 (goto-char (point-min))
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
1528 (forward-line 1)
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
1529 (while
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
1530 (and (member (buffer-substring-no-properties
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
1531 (line-beginning-position) (line-end-position))
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
1532 active)
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
1533 (zerop (forward-line 1))))
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
1534 (if (or (eobp) (null active))
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
1535 (delete-overlay mpc-separator-ol)
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
1536 (move-overlay mpc-separator-ol (1- (point)) (point))))
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
1537
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
1538 (defun mpc-sort (active)
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
1539 ;; Sort the active elements at the front.
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
1540 (let ((inhibit-read-only t))
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
1541 (goto-char (point-min))
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
1542 (if (mpc-tagbrowser-all-p) (forward-line 1))
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
1543 (condition-case nil
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
1544 (sort-subr nil 'forward-line 'end-of-line
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
1545 nil nil
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
1546 (lambda (s1 s2)
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
1547 (setq s1 (buffer-substring-no-properties
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
1548 (car s1) (cdr s1)))
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
1549 (setq s2 (buffer-substring-no-properties
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
1550 (car s2) (cdr s2)))
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
1551 (cond
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
1552 ((member s1 active)
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
1553 (if (member s2 active)
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
1554 (let ((cmp (mpc-compare-strings s1 s2 t)))
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
1555 (and (numberp cmp) (< cmp 0)))
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
1556 t))
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
1557 ((member s2 active) nil)
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
1558 (t (let ((cmp (mpc-compare-strings s1 s2 t)))
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
1559 (and (numberp cmp) (< cmp 0)))))))
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
1560 ;; The comparison predicate arg is new in Emacs-22.
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
1561 (wrong-number-of-arguments
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
1562 (sort-subr nil 'forward-line 'end-of-line
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
1563 (lambda ()
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
1564 (let ((name (buffer-substring-no-properties
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
1565 (point) (line-end-position))))
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
1566 (cond
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
1567 ((member name active) (concat "1" name))
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
1568 (t (concat "2" "name"))))))))))
|
106354
|
1569
|
106342
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
1570 (defvar mpc--changed-selection)
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
1571
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
1572 (defun mpc-reorder (&optional nodeactivate)
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
1573 "Reorder entries based on thre currently active selections.
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
1574 I.e. split the current browser buffer into a first part containing the
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
1575 entries included in the selection, then a separator, and then the entries
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
1576 not included in the selection.
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
1577 Return non-nil if a selection was deactivated."
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
1578 (mpc-select-save
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
1579 (let ((constraints (mpc-constraints-get-current (current-buffer)))
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
1580 (active 'all))
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
1581 ;; (unless (equal constraints mpc-constraints)
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
1582 ;; (set (make-local-variable 'mpc-constraints) constraints)
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
1583 (dolist (cst constraints)
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
1584 (let ((vals (apply 'mpc-union
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
1585 (mapcar (lambda (val)
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
1586 (mpc-cmd-list mpc-tag (car cst) val))
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
1587 (cdr cst)))))
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
1588 (setq active
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
1589 (if (listp active) (mpc-intersection active vals) vals))))
|
106354
|
1590
|
106342
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
1591 (when (and (listp active))
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
1592 ;; Remove the selections if they are all in conflict with
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
1593 ;; other constraints.
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
1594 (let ((deactivate t))
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
1595 (dolist (sel selection)
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
1596 (when (member sel active) (setq deactivate nil)))
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
1597 (when deactivate
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
1598 ;; Variable declared/used by `mpc-select-save'.
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
1599 (when selection
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
1600 (setq mpc--changed-selection t))
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
1601 (unless nodeactivate
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
1602 (setq selection nil)
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
1603 (mapc 'delete-overlay mpc-select)
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
1604 (setq mpc-select nil)
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
1605 (mpc-tagbrowser-all-select)))))
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
1606
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
1607 ;; FIXME: This `mpc-sort' takes a lot of time. Maybe we should
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
1608 ;; be more clever and presume the buffer is mostly sorted already.
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
1609 (mpc-sort (if (listp active) active))
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
1610 (mpc-separator (if (listp active) active)))))
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
1611
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
1612 (defun mpc-selection-refresh ()
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
1613 (let ((mpc--changed-selection t))
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
1614 (while mpc--changed-selection
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
1615 (setq mpc--changed-selection nil)
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
1616 (dolist (buf (process-get (mpc-proc) 'buffers))
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
1617 (setq buf (cdr buf))
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
1618 (when (and (buffer-local-value 'mpc-tag buf)
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
1619 (not (eq buf (current-buffer))))
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
1620 (with-current-buffer buf (mpc-reorder)))))
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
1621 ;; FIXME: reorder the current buffer last and prevent deactivation,
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
1622 ;; since whatever selection we made here is the most recent one
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
1623 ;; and should hence take precedence.
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
1624 (when mpc-tag (mpc-reorder 'nodeactivate))
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
1625 ;; FIXME: comment?
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
1626 (if (and mpc--song-search mpc--changed-selection)
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
1627 (progn
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
1628 (setq mpc--song-search nil)
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
1629 (mpc-selection-refresh))
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
1630 (mpc-songs-refresh))))
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
1631
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
1632 ;;; Hierarchical tagbrowser ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
1633 ;; Todo:
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
1634 ;; - Add a button on each dir to open/close it (?)
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
1635 ;; - add the parent dir on the previous line, greyed-out, if it's not
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
1636 ;; present (because we're in the non-selected part and the parent is
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
1637 ;; in the selected part).
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
1638
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
1639 (defvar mpc-tagbrowser-dir-mode-map
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
1640 (let ((map (make-sparse-keymap)))
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
1641 (set-keymap-parent map mpc-tagbrowser-mode-map)
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
1642 (define-key map [?\M-\C-m] 'mpc-tagbrowser-dir-toggle)
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
1643 map))
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
1644
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
1645 ;; (defvar mpc-tagbrowser-dir-keywords
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
1646 ;; '(mpc-tagbrowser-dir-hide-prefix))
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
1647
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
1648 (define-derived-mode mpc-tagbrowser-dir-mode mpc-tagbrowser-mode '("MPC-" mpc-tag-name)
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
1649 ;; (set (make-local-variable 'font-lock-defaults)
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
1650 ;; '(mpc-tagbrowser-dir-keywords t))
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
1651 )
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
1652
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
1653 ;; (defun mpc-tagbrowser-dir-hide-prefix (limit)
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
1654 ;; (while
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
1655 ;; (let ((prev (buffer-substring (line-beginning-position 0)
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
1656 ;; (line-end-position 0))))
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
1657 ;; (
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
1658
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
1659 (defun mpc-tagbrowser-dir-toggle (event)
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
1660 "Open or close the element at point."
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
1661 (interactive (list last-nonmenu-event))
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
1662 (mpc-event-set-point event)
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
1663 (let ((name (buffer-substring (line-beginning-position)
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
1664 (line-end-position)))
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
1665 (prop (intern mpc-tag)))
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
1666 (if (not (member name (process-get (mpc-proc) prop)))
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
1667 (process-put (mpc-proc) prop
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
1668 (cons name (process-get (mpc-proc) prop)))
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
1669 (let ((new (delete name (process-get (mpc-proc) prop))))
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
1670 (setq name (concat name "/"))
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
1671 (process-put (mpc-proc) prop
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
1672 (delq nil
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
1673 (mapcar (lambda (x)
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
1674 (if (mpc-string-prefix-p name x)
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
1675 nil x))
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
1676 new)))))
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
1677 (mpc-tagbrowser-refresh)))
|
106354
|
1678
|
106342
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
1679
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
1680 ;;; Playlist management ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
1681
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
1682 (defvar mpc-songs-playlist nil
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
1683 "Name of the currently selected playlist, if any.
|
106365
|
1684 A value of t means the main playlist.")
|
106342
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
1685 (make-variable-buffer-local 'mpc-songs-playlist)
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
1686
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
1687 (defun mpc-playlist-create (name)
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
1688 "Save current playlist under name NAME."
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
1689 (interactive "sPlaylist name: ")
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
1690 (mpc-proc-cmd (list "save" name))
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
1691 (let ((buf (mpc-proc-buffer (mpc-proc) 'Playlist)))
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
1692 (when (buffer-live-p buf)
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
1693 (with-current-buffer buf (mpc-tagbrowser-refresh)))))
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
1694
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
1695 (defun mpc-playlist-destroy (name)
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
1696 "Delete playlist named NAME."
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
1697 (interactive
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
1698 (list (completing-read "Delete playlist: " (mpc-cmd-list 'Playlist)
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
1699 nil 'require-match)))
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
1700 (mpc-proc-cmd (list "rm" name))
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
1701 (let ((buf (mpc-proc-buffer (mpc-proc) 'Playlist)))
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
1702 (when (buffer-live-p buf)
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
1703 (with-current-buffer buf (mpc-tagbrowser-refresh)))))
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
1704
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
1705 (defun mpc-playlist-rename (oldname newname)
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
1706 "Rename playlist OLDNAME to NEWNAME."
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
1707 (interactive
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
1708 (let* ((oldname (if (and (eq mpc-tag 'Playlist) (null current-prefix-arg))
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
1709 (buffer-substring (line-beginning-position)
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
1710 (line-end-position))
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
1711 (completing-read "Rename playlist: "
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
1712 (mpc-cmd-list 'Playlist)
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
1713 nil 'require-match)))
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
1714 (newname (read-string (format "Rename '%s' to: " oldname))))
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
1715 (if (zerop (length newname))
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
1716 (error "Aborted")
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
1717 (list oldname newname))))
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
1718 (mpc-proc-cmd (list "rename" oldname newname))
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
1719 (let ((buf (mpc-proc-buffer (mpc-proc) 'Playlist)))
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
1720 (if (buffer-live-p buf)
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
1721 (with-current-buffer buf (mpc-tagbrowser-refresh)))))
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
1722
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
1723 (defun mpc-playlist ()
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
1724 "Show the current playlist."
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
1725 (interactive)
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
1726 (mpc-constraints-push 'noerror)
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
1727 (mpc-constraints-restore '()))
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
1728
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
1729 (defun mpc-playlist-add ()
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
1730 "Add the selection to the playlist."
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
1731 (interactive)
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
1732 (let ((songs (mapcar #'car (mpc-songs-selection))))
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
1733 (mpc-cmd-add songs)
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
1734 (message "Appended %d songs" (length songs))
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
1735 ;; Return the songs added. Used in `mpc-play'.
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
1736 songs))
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
1737
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
1738 (defun mpc-playlist-delete ()
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
1739 "Remove the selected songs from the playlist."
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
1740 (interactive)
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
1741 (unless mpc-songs-playlist
|
106697
|
1742 (error "The selected songs aren't part of a playlist"))
|
106342
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
1743 (let ((song-poss (mapcar #'cdr (mpc-songs-selection))))
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
1744 (mpc-cmd-delete song-poss mpc-songs-playlist)
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
1745 (mpc-songs-refresh)
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
1746 (message "Deleted %d songs" (length song-poss))))
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
1747
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
1748 ;;; Volume management ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
1749
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
1750 (defvar mpc-volume-map
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
1751 (let ((map (make-sparse-keymap)))
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
1752 (define-key map [down-mouse-1] 'mpc-volume-mouse-set)
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
1753 (define-key map [mouse-1] 'ignore)
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
1754 (define-key map [header-line down-mouse-1] 'mpc-volume-mouse-set)
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
1755 (define-key map [header-line mouse-1] 'ignore)
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
1756 (define-key map [mode-line down-mouse-1] 'mpc-volume-mouse-set)
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
1757 (define-key map [mode-line mouse-1] 'ignore)
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
1758 map))
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
1759
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
1760 (defvar mpc-volume nil) (put 'mpc-volume 'risky-local-variable t)
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
1761
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
1762 (defun mpc-volume-refresh ()
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
1763 ;; Maintain the volume.
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
1764 (setq mpc-volume
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
1765 (mpc-volume-widget
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
1766 (string-to-number (cdr (assq 'volume mpc-status))))))
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
1767
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
1768 (defvar mpc-volume-step 5)
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
1769
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
1770 (defun mpc-volume-mouse-set (&optional event)
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
1771 "Change volume setting."
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
1772 (interactive (list last-nonmenu-event))
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
1773 (let* ((posn (event-start event))
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
1774 (diff
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
1775 (if (memq (if (stringp (car-safe (posn-object posn)))
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
1776 (aref (car (posn-object posn)) (cdr (posn-object posn)))
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
1777 (with-current-buffer (window-buffer (posn-window posn))
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
1778 (char-after (posn-point posn))))
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
1779 '(?◁ ?<))
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
1780 (- mpc-volume-step) mpc-volume-step))
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
1781 (newvol (+ (string-to-number (cdr (assq 'volume mpc-status))) diff)))
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
1782 (mpc-proc-cmd (list "setvol" newvol) 'mpc-status-refresh)
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
1783 (message "Set MPD volume to %s%%" newvol)))
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
1784
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
1785 (defun mpc-volume-widget (vol &optional size)
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
1786 (unless size (setq size 12.5))
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
1787 (let ((scaledvol (* (/ vol 100.0) size)))
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
1788 ;; (message "Volume sizes: %s - %s" (/ vol fact) (/ (- 100 vol) fact))
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
1789 (list (propertize "<" ;; "◁"
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
1790 ;; 'face 'default
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
1791 'keymap mpc-volume-map
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
1792 'face '(:box (:line-width -2 :style pressed-button))
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
1793 'mouse-face '(:box (:line-width -2 :style released-button)))
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
1794 " "
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
1795 (propertize "a"
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
1796 'display (list 'space :width scaledvol)
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
1797 'face '(:inverse-video t
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
1798 :box (:line-width -2 :style released-button)))
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
1799 (propertize "a"
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
1800 'display (list 'space :width (- size scaledvol))
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
1801 'face '(:box (:line-width -2 :style released-button)))
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
1802 " "
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
1803 (propertize ">" ;; "▷"
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
1804 ;; 'face 'default
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
1805 'keymap mpc-volume-map
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
1806 'face '(:box (:line-width -2 :style pressed-button))
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
1807 'mouse-face '(:box (:line-width -2 :style released-button))))))
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
1808
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
1809 ;;; MPC songs mode ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
1810
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
1811 (defvar mpc-current-song nil) (put 'mpc-current-song 'risky-local-variable t)
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
1812 (defvar mpc-current-updating nil) (put 'mpc-current-updating 'risky-local-variable t)
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
1813 (defvar mpc-songs-format-description nil) (put 'mpc-songs-format-description 'risky-local-variable t)
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
1814
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
1815 (defvar mpc-previous-window-config nil)
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
1816
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
1817 (defvar mpc-songs-mode-map
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
1818 (let ((map (make-sparse-keymap)))
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
1819 (set-keymap-parent map mpc-mode-map)
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
1820 (define-key map [remap mpc-select] 'mpc-songs-jump-to)
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
1821 map))
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
1822
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
1823 (defvar mpc-songpointer-set-visible nil)
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
1824
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
1825 (defvar mpc-songs-hashcons (make-hash-table :test 'equal :weakness t)
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
1826 "Make song file name objects unique via hash consing.
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
1827 This is used so that they can be compared with `eq', which is needed for
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
1828 `text-property-any'.")
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
1829 (defun mpc-songs-hashcons (name)
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
1830 (or (gethash name mpc-songs-hashcons) (puthash name name mpc-songs-hashcons)))
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
1831 (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
|
1832 "Format used to display each song in the list of songs."
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
1833 :type 'string)
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
1834
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
1835 (defvar mpc-songs-totaltime)
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
1836
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
1837 (defun mpc-songs-refresh ()
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
1838 (let ((buf (mpc-proc-buffer (mpc-proc) 'songs)))
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
1839 (when (buffer-live-p buf)
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
1840 (with-current-buffer buf
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
1841 (let ((constraints (mpc-constraints-get-current (current-buffer)))
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
1842 (dontsort nil)
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
1843 (inhibit-read-only t)
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
1844 (totaltime 0)
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
1845 (curline (cons (count-lines (point-min)
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
1846 (line-beginning-position))
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
1847 (buffer-substring (line-beginning-position)
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
1848 (line-end-position))))
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
1849 active)
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
1850 (setq mpc-songs-playlist nil)
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
1851 (if (null constraints)
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
1852 ;; When there are no constraints, rather than show the list of
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
1853 ;; all songs (which could take a while to download and
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
1854 ;; format), we show the current playlist.
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
1855 ;; FIXME: it would be good to be able to show the complete
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
1856 ;; list, but that would probably require us to format it
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
1857 ;; on-the-fly to make it bearable.
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
1858 (setq dontsort t
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
1859 mpc-songs-playlist t
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
1860 active (mpc-proc-buf-to-alists
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
1861 (mpc-proc-cmd "playlistinfo")))
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
1862 (dolist (cst constraints)
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
1863 (if (and (eq (car cst) 'Playlist)
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
1864 (= 1 (length (cdr cst))))
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
1865 (setq mpc-songs-playlist (cadr cst)))
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
1866 ;; We don't do anything really special here for playlists,
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
1867 ;; because it's unclear what's a correct "union" of playlists.
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
1868 (let ((vals (apply 'mpc-union
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
1869 (mapcar (lambda (val)
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
1870 (mpc-cmd-find (car cst) val))
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
1871 (cdr cst)))))
|
107541
|
1872 (setq active (cond
|
|
1873 ((null active)
|
106342
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
1874 (if (eq (car cst) 'Playlist)
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
1875 (setq dontsort t))
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
1876 vals)
|
107541
|
1877 ((or dontsort
|
106342
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
1878 ;; Try to preserve ordering and
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
1879 ;; repetitions from playlists.
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
1880 (not (eq (car cst) 'Playlist)))
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
1881 (mpc-intersection active vals
|
107541
|
1882 (lambda (x) (assq 'file x))))
|
|
1883 (t
|
106342
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
1884 (setq dontsort t)
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
1885 (mpc-intersection vals active
|
107541
|
1886 (lambda (x)
|
|
1887 (assq 'file x)))))))))
|
106342
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
1888 (mpc-select-save
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
1889 (erase-buffer)
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
1890 ;; Sorting songs is surprisingly difficult: when comparing two
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
1891 ;; songs with the same album name but different artist name, you
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
1892 ;; have to know whether these are two different albums (with the
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
1893 ;; same name) or a single album (typically a compilation).
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
1894 ;; I punt on it and just use file-name sorting, which does the
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
1895 ;; right thing if your library is properly arranged.
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
1896 (dolist (song (if dontsort active
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
1897 (sort active
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
1898 (lambda (song1 song2)
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
1899 (let ((cmp (mpc-compare-strings
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
1900 (cdr (assq 'file song1))
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
1901 (cdr (assq 'file song2)))))
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
1902 (and (integerp cmp) (< cmp 0)))))))
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
1903 (incf totaltime (string-to-number (or (cdr (assq 'Time song)) "0")))
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
1904 (mpc-format mpc-songs-format song)
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
1905 (delete-char (- (skip-chars-backward " "))) ;Remove trailing space.
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
1906 (insert "\n")
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
1907 (put-text-property
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
1908 (line-beginning-position 0) (line-beginning-position)
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
1909 'mpc-file (mpc-songs-hashcons (cdr (assq 'file song))))
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
1910 (let ((pos (assq 'Pos song)))
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
1911 (if pos
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
1912 (put-text-property
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
1913 (line-beginning-position 0) (line-beginning-position)
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
1914 'mpc-file-pos (string-to-number (cdr pos)))))
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
1915 ))
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
1916 (goto-char (point-min))
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
1917 (forward-line (car curline))
|
107541
|
1918 (if (or (search-forward (cdr curline) nil t)
|
106342
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
1919 (search-backward (cdr curline) nil t))
|
107541
|
1920 (beginning-of-line)
|
|
1921 (goto-char (point-min)))
|
106342
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
1922 (set (make-local-variable 'mpc-songs-totaltime)
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
1923 (unless (zerop totaltime)
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
1924 (list " " (mpc-secs-to-time totaltime))))
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
1925 ))))
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
1926 (let ((mpc-songpointer-set-visible t))
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
1927 (mpc-songpointer-refresh)))
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
1928
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
1929 (defun mpc-songs-search (string)
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
1930 "Filter songs to those who include STRING in their metadata."
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
1931 (interactive "sSearch for: ")
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
1932 (setq mpc--song-search
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
1933 (if (zerop (length string)) nil string))
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
1934 (let ((mpc--changed-selection t))
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
1935 (while mpc--changed-selection
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
1936 (setq mpc--changed-selection nil)
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
1937 (dolist (buf (process-get (mpc-proc) 'buffers))
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
1938 (setq buf (cdr buf))
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
1939 (when (buffer-local-value 'mpc-tag buf)
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
1940 (with-current-buffer buf (mpc-reorder))))
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
1941 (mpc-songs-refresh))))
|
106354
|
1942
|
106342
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
1943 (defun mpc-songs-kill-search ()
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
1944 "Turn off the current search restriction."
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
1945 (interactive)
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
1946 (mpc-songs-search nil))
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
1947
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
1948 (defun mpc-songs-selection ()
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
1949 "Return the list of songs currently selected."
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
1950 (let ((buf (mpc-proc-buffer (mpc-proc) 'songs)))
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
1951 (when (buffer-live-p buf)
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
1952 (with-current-buffer buf
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
1953 (save-excursion
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
1954 (let ((files ()))
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
1955 (if mpc-select
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
1956 (dolist (ol mpc-select)
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
1957 (push (cons
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
1958 (get-text-property (overlay-start ol) 'mpc-file)
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
1959 (get-text-property (overlay-start ol) 'mpc-file-pos))
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
1960 files))
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
1961 (goto-char (point-min))
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
1962 (while (not (eobp))
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
1963 (push (cons
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
1964 (get-text-property (point) 'mpc-file)
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
1965 (get-text-property (point) 'mpc-file-pos))
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
1966 files)
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
1967 (forward-line 1)))
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
1968 (nreverse files)))))))
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
1969
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
1970 (defun mpc-songs-jump-to (song-file &optional posn)
|
106365
|
1971 "Jump to song SONG-FILE; interactively, this is the song at point."
|
106342
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
1972 (interactive
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
1973 (let* ((event last-nonmenu-event)
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
1974 (posn (event-end event)))
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
1975 (with-selected-window (posn-window posn)
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
1976 (goto-char (posn-point posn))
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
1977 (list (get-text-property (point) 'mpc-file)
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
1978 posn))))
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
1979 (let* ((plbuf (mpc-proc-cmd "playlist"))
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
1980 (re (concat "^\\([0-9]+\\):" (regexp-quote song-file) "$"))
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
1981 (sn (with-current-buffer plbuf
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
1982 (goto-char (point-min))
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
1983 (when (re-search-forward re nil t)
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
1984 (match-string 1)))))
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
1985 (cond
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
1986 ((null sn) (error "This song is not in the playlist"))
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
1987 ((null (with-current-buffer plbuf (re-search-forward re nil t)))
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
1988 ;; song-file only appears once in the playlist: no ambiguity,
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
1989 ;; we're good to go!
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
1990 (mpc-proc-cmd (list "play" sn)))
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
1991 (t
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
1992 ;; The song appears multiple times in the playlist. If the current
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
1993 ;; buffer holds not only the destination song but also the current
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
1994 ;; song, then we will move in the playlist to the same relative
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
1995 ;; position as in the buffer. Otherwise, we will simply choose the
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
1996 ;; song occurrence closest to the current song.
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
1997 (with-selected-window (posn-window posn)
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
1998 (let* ((cur (and (markerp overlay-arrow-position)
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
1999 (marker-position overlay-arrow-position)))
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
2000 (dest (save-excursion
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
2001 (goto-char (posn-point posn))
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
2002 (line-beginning-position)))
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
2003 (lines (when cur (* (if (< cur dest) 1 -1)
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
2004 (count-lines cur dest)))))
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
2005 (with-current-buffer plbuf
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
2006 (goto-char (point-min))
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
2007 ;; Start the search from the current song.
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
2008 (forward-line (string-to-number
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
2009 (or (cdr (assq 'song mpc-status)) "0")))
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
2010 ;; If the current song is also displayed in the buffer,
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
2011 ;; then try to move to the same relative position.
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
2012 (if lines (forward-line lines))
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
2013 ;; Now search the closest occurrence.
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
2014 (let* ((next (save-excursion
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
2015 (when (re-search-forward re nil t)
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
2016 (cons (point) (match-string 1)))))
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
2017 (prev (save-excursion
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
2018 (when (re-search-backward re nil t)
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
2019 (cons (point) (match-string 1)))))
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
2020 (sn (cdr (if (and next prev)
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
2021 (if (< (- (car next) (point))
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
2022 (- (point) (car prev)))
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
2023 next prev)
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
2024 (or next prev)))))
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
2025 (assert sn)
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
2026 (mpc-proc-cmd (concat "play " sn))))))))))
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
2027
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
2028 (define-derived-mode mpc-songs-mode mpc-mode "MPC-song"
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
2029 (setq mpc-songs-format-description
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
2030 (with-temp-buffer (mpc-format mpc-songs-format 'self) (buffer-string)))
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
2031 (set (make-local-variable 'header-line-format)
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
2032 ;; '("MPC " mpc-volume " " mpc-current-song)
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
2033 (list (propertize " " 'display '(space :align-to 0))
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
2034 ;; 'mpc-songs-format-description
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
2035 '(:eval
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
2036 (let ((hscroll (window-hscroll)))
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
2037 (with-temp-buffer
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
2038 (mpc-format mpc-songs-format 'self hscroll)
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
2039 ;; That would be simpler than the hscroll handling in
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
2040 ;; mpc-format, but currently move-to-column does not
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
2041 ;; recognize :space display properties.
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
2042 ;; (move-to-column hscroll)
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
2043 ;; (delete-region (point-min) (point))
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
2044 (buffer-string))))))
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
2045 (set (make-local-variable 'mode-line-format)
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
2046 '("%e" mode-line-frame-identification mode-line-buffer-identification
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
2047 #(" " 0 3
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
2048 (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
|
2049 mode-line-position
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
2050 #(" " 0 2
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
2051 (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
|
2052 mpc-songs-totaltime
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
2053 mpc-current-updating
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
2054 #(" " 0 2
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
2055 (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
|
2056 (mpc--song-search
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
2057 (:propertize
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
2058 ("Search=\"" mpc--song-search "\"")
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
2059 help-echo "mouse-2: kill this search"
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
2060 follow-link t
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
2061 mouse-face mode-line-highlight
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
2062 keymap (keymap (mode-line keymap
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
2063 (mouse-2 . mpc-songs-kill-search))))
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
2064 (:propertize "NoSearch"
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
2065 help-echo "mouse-2: set a search restriction"
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
2066 follow-link t
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
2067 mouse-face mode-line-highlight
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
2068 keymap (keymap (mode-line keymap (mouse-2 . mpc-songs-search)))))))
|
106354
|
2069
|
106342
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
2070 ;; (set (make-local-variable 'mode-line-process)
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
2071 ;; '("" ;; mpc-volume " "
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
2072 ;; mpc-songs-totaltime
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
2073 ;; mpc-current-updating))
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
2074 )
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
2075
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
2076 (defun mpc-songpointer-set (pos)
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
2077 (let* ((win (get-buffer-window (current-buffer) t))
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
2078 (visible (when win
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
2079 (or mpc-songpointer-set-visible
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
2080 (and (markerp overlay-arrow-position)
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
2081 (eq (marker-buffer overlay-arrow-position)
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
2082 (current-buffer))
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
2083 (<= (window-start win) overlay-arrow-position)
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
2084 (< overlay-arrow-position (window-end win)))))))
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
2085 (unless (local-variable-p 'overlay-arrow-position)
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
2086 (set (make-local-variable 'overlay-arrow-position) (make-marker)))
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
2087 (move-marker overlay-arrow-position pos)
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
2088 ;; If the arrow was visible, try to keep it that way.
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
2089 (if (and visible pos
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
2090 (or (> (window-start win) pos) (>= pos (window-end win t))))
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
2091 (set-window-point win pos))))
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
2092
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
2093 (defun mpc-songpointer-refresh ()
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
2094 (let ((buf (mpc-proc-buffer (mpc-proc) 'songs)))
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
2095 (when (buffer-live-p buf)
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
2096 (with-current-buffer buf
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
2097 (let* ((pos (text-property-any
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
2098 (point-min) (point-max)
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
2099 'mpc-file (mpc-songs-hashcons
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
2100 (cdr (assq 'file mpc-status)))))
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
2101 (other (when pos
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
2102 (save-excursion
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
2103 (goto-char pos)
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
2104 (text-property-any
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
2105 (line-beginning-position 2) (point-max)
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
2106 'mpc-file (mpc-songs-hashcons
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
2107 (cdr (assq 'file mpc-status))))))))
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
2108 (if other
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
2109 ;; The song appears multiple times in the buffer.
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
2110 ;; We need to be careful to choose the right occurrence.
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
2111 (mpc-proc-cmd "playlist" 'mpc-songpointer-refresh-hairy)
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
2112 (mpc-songpointer-set pos)))))))
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
2113
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
2114 (defun mpc-songpointer-context (size plbuf)
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
2115 (with-current-buffer plbuf
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
2116 (goto-char (point-min))
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
2117 (forward-line (string-to-number (or (cdr (assq 'song mpc-status)) "0")))
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
2118 (let ((context-before '())
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
2119 (context-after '()))
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
2120 (save-excursion
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
2121 (dotimes (i size)
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
2122 (when (re-search-backward "^[0-9]+:\\(.*\\)" nil t)
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
2123 (push (mpc-songs-hashcons (match-string 1)) context-before))))
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
2124 ;; Skip the actual current song.
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
2125 (forward-line 1)
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
2126 (dotimes (i size)
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
2127 (when (re-search-forward "^[0-9]+:\\(.*\\)" nil t)
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
2128 (push (mpc-songs-hashcons (match-string 1)) context-after)))
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
2129 ;; If there isn't `size' context, then return nil.
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
2130 (unless (and (< (length context-before) size)
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
2131 (< (length context-after) size))
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
2132 (cons (nreverse context-before) (nreverse context-after))))))
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
2133
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
2134 (defun mpc-songpointer-score (context pos)
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
2135 (let ((count 0))
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
2136 (goto-char pos)
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
2137 (dolist (song (car context))
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
2138 (and (zerop (forward-line -1))
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
2139 (eq (get-text-property (point) 'mpc-file) song)
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
2140 (incf count)))
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
2141 (goto-char pos)
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
2142 (dolist (song (cdr context))
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
2143 (and (zerop (forward-line 1))
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
2144 (eq (get-text-property (point) 'mpc-file) song)
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
2145 (incf count)))
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
2146 count))
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
2147
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
2148 (defun mpc-songpointer-refresh-hairy ()
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
2149 ;; Based on the complete playlist, we should figure out where in the
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
2150 ;; song buffer is the currently playing song.
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
2151 (let ((plbuf (current-buffer))
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
2152 (buf (mpc-proc-buffer (mpc-proc) 'songs)))
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
2153 (when (buffer-live-p buf)
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
2154 (with-current-buffer buf
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
2155 (let* ((context-size 0)
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
2156 (context '(() . ()))
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
2157 (pos (text-property-any
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
2158 (point-min) (point-max)
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
2159 'mpc-file (mpc-songs-hashcons
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
2160 (cdr (assq 'file mpc-status)))))
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
2161 (score 0)
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
2162 (other pos))
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
2163 (while
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
2164 (setq other
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
2165 (save-excursion
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
2166 (goto-char other)
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
2167 (text-property-any
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
2168 (line-beginning-position 2) (point-max)
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
2169 'mpc-file (mpc-songs-hashcons
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
2170 (cdr (assq 'file mpc-status))))))
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
2171 ;; There is an `other' contestant.
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
2172 (let ((other-score (mpc-songpointer-score context other)))
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
2173 (cond
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
2174 ;; `other' is worse: try the next one.
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
2175 ((< other-score score) nil)
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
2176 ;; `other' is better: remember it and then search further.
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
2177 ((> other-score score)
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
2178 (setq pos other)
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
2179 (setq score other-score))
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
2180 ;; Both are equal and increasing the context size won't help.
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
2181 ;; Arbitrarily choose one of the two and keep looking
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
2182 ;; for a better match.
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
2183 ((< score context-size) nil)
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
2184 (t
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
2185 ;; Score is equal and increasing context might help: try it.
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
2186 (incf context-size)
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
2187 (let ((new-context
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
2188 (mpc-songpointer-context context-size plbuf)))
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
2189 (if (null new-context)
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
2190 ;; There isn't more context: choose one arbitrarily
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
2191 ;; and keep looking for a better match elsewhere.
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
2192 (decf context-size)
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
2193 (setq context new-context)
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
2194 (setq score (mpc-songpointer-score context pos))
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
2195 (save-excursion
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
2196 (goto-char other)
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
2197 ;; Go back one line so we find `other' again.
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
2198 (setq other (line-beginning-position 0)))))))))
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
2199 (mpc-songpointer-set pos))))))
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
2200
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
2201 (defun mpc-current-refresh ()
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
2202 ;; Maintain the current data.
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
2203 (mpc-status-buffer-refresh)
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
2204 (setq mpc-current-updating
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
2205 (if (assq 'updating_db mpc-status) " Updating-DB"))
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
2206 (ignore-errors
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
2207 (setq mpc-current-song
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
2208 (when (assq 'file mpc-status)
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
2209 (concat " "
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
2210 (mpc-secs-to-time (cdr (assq 'time mpc-status)))
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
2211 " "
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
2212 (cdr (assq 'Title mpc-status))
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
2213 " ("
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
2214 (cdr (assq 'Artist mpc-status))
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
2215 " / "
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
2216 (cdr (assq 'Album mpc-status))
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
2217 ")"))))
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
2218 (force-mode-line-update t))
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
2219
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
2220 (defun mpc-songs-buf ()
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
2221 (let ((buf (mpc-proc-buffer (mpc-proc) 'songs)))
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
2222 (if (buffer-live-p buf) buf
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
2223 (with-current-buffer (setq buf (get-buffer-create "*MPC-Songs*"))
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
2224 (mpc-proc-buffer (mpc-proc) 'songs buf)
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
2225 (mpc-songs-mode)
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
2226 buf))))
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
2227
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
2228 (defun mpc-update ()
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
2229 "Tell MPD to refresh its database."
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
2230 (interactive)
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
2231 (mpc-cmd-update))
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
2232
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
2233 (defun mpc-quit ()
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
2234 "Quit Music Player Daemon."
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
2235 (interactive)
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
2236 (let* ((proc mpc-proc)
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
2237 (bufs (mapcar 'cdr (if proc (process-get proc 'buffers))))
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
2238 (wins (mapcar (lambda (buf) (get-buffer-window buf 0)) bufs))
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
2239 (song-buf (mpc-songs-buf))
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
2240 frames)
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
2241 ;; Collect all the frames where MPC buffers appear.
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
2242 (dolist (win wins)
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
2243 (when (and win (not (memq (window-frame win) frames)))
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
2244 (push (window-frame win) frames)))
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
2245 (if (and frames song-buf
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
2246 (with-current-buffer song-buf mpc-previous-window-config))
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
2247 (progn
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
2248 (select-frame (car frames))
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
2249 (set-window-configuration
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
2250 (with-current-buffer song-buf mpc-previous-window-config)))
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
2251 ;; Now delete the ones that show nothing else than MPC buffers.
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
2252 (dolist (frame frames)
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
2253 (let ((delete t))
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
2254 (dolist (win (window-list frame))
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
2255 (unless (memq (window-buffer win) bufs) (setq delete nil)))
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
2256 (if delete (ignore-errors (delete-frame frame))))))
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
2257 ;; Then kill the buffers.
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
2258 (mapc 'kill-buffer bufs)
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
2259 (mpc-status-stop)
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
2260 (if proc (delete-process proc))))
|
106354
|
2261
|
106342
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
2262 (defun mpc-stop ()
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
2263 "Stop playing the current queue of songs."
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
2264 (interactive)
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
2265 (mpc-cmd-stop)
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
2266 (mpc-cmd-clear)
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
2267 (mpc-status-refresh))
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
2268
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
2269 (defun mpc-pause ()
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
2270 "Pause playing."
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
2271 (interactive)
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
2272 (mpc-cmd-pause "1"))
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
2273
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
2274 (defun mpc-resume ()
|
106365
|
2275 "Resume playing."
|
106342
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
2276 (interactive)
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
2277 (mpc-cmd-pause "0"))
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
2278
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
2279 (defun mpc-play ()
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
2280 "Start playing whatever is selected."
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
2281 (interactive)
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
2282 (if (member (cdr (assq 'state (mpc-cmd-status))) '("pause"))
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
2283 (mpc-resume)
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
2284 ;; When playing the playlist ends, the playlist isn't cleared, but the
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
2285 ;; user probably doesn't want to re-listen to it before getting to
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
2286 ;; listen to what he just selected.
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
2287 ;; (if (member (cdr (assq 'state (mpc-cmd-status))) '("stop"))
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
2288 ;; (mpc-cmd-clear))
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
2289 ;; Actually, we don't use mpc-play to append to the playlist any more,
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
2290 ;; so we can just always empty the playlist.
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
2291 (mpc-cmd-clear)
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
2292 (if (mpc-playlist-add)
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
2293 (if (member (cdr (assq 'state (mpc-cmd-status))) '("stop"))
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
2294 (mpc-cmd-play))
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
2295 (error "Don't know what to play"))))
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
2296
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
2297 (defun mpc-next ()
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
2298 "Jump to the next song in the queue."
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
2299 (interactive)
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
2300 (mpc-proc-cmd "next")
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
2301 (mpc-status-refresh))
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
2302
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
2303 (defun mpc-prev ()
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
2304 "Jump to the beginning of the current song, or to the previous song."
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
2305 (interactive)
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
2306 (let ((time (cdr (assq 'time mpc-status))))
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
2307 ;; Here we rely on the fact that string-to-number silently ignores
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
2308 ;; everything after a non-digit char.
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
2309 (cond
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
2310 ;; Go back to the beginning of current song.
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
2311 ((and time (> (string-to-number time) 0))
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
2312 (mpc-proc-cmd (list "seekid" (cdr (assq 'songid mpc-status)) 0)))
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
2313 ;; We're at the beginning of the first song of the playlist.
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
2314 ;; Fetch the previous one from `mpc-queue-back'.
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
2315 ;; ((and (zerop (string-to-number (cdr (assq 'song mpc-status))))
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
2316 ;; mpc-queue-back)
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
2317 ;; ;; Because we use cmd-list rather than cmd-play, the queue is not
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
2318 ;; ;; automatically updated.
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
2319 ;; (let ((prev (pop mpc-queue-back)))
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
2320 ;; (push prev mpc-queue)
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
2321 ;; (mpc-proc-cmd
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
2322 ;; (mpc-proc-cmd-list
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
2323 ;; (list (list "add" prev)
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
2324 ;; (list "move" (cdr (assq 'playlistlength mpc-status)) "0")
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
2325 ;; "previous")))))
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
2326 ;; We're at the beginning of a song, but not the first one.
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
2327 (t (mpc-proc-cmd "previous")))
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
2328 (mpc-status-refresh)))
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
2329
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
2330 (defvar mpc-last-seek-time '(0 . 0))
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
2331
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
2332 (defun mpc--faster (event speedup step)
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
2333 "Fast forward."
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
2334 (interactive (list last-nonmenu-event))
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
2335 (let ((repeat-delay (/ (abs (float step)) speedup)))
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
2336 (if (not (memq 'down (event-modifiers event)))
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
2337 (let* ((currenttime (float-time))
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
2338 (last-time (- currenttime (car mpc-last-seek-time))))
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
2339 (if (< last-time (* 0.9 repeat-delay))
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
2340 nil ;; Trottle
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
2341 (let* ((status (if (< last-time 1.0)
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
2342 mpc-status (mpc-cmd-status)))
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
2343 (songid (cdr (assq 'songid status)))
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
2344 (time (if songid
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
2345 (if (< last-time 1.0)
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
2346 (cdr mpc-last-seek-time)
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
2347 (string-to-number
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
2348 (cdr (assq 'time status)))))))
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
2349 (setq mpc-last-seek-time
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
2350 (cons currenttime (setq time (+ time step))))
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
2351 (mpc-proc-cmd (list "seekid" songid time)
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
2352 'mpc-status-refresh))))
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
2353 (let ((status (mpc-cmd-status)))
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
2354 (lexical-let* ((songid (cdr (assq 'songid status)))
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
2355 (step step)
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
2356 (time (if songid (string-to-number
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
2357 (cdr (assq 'time status))))))
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
2358 (let ((timer (run-with-timer
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
2359 t repeat-delay
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
2360 (lambda ()
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
2361 (mpc-proc-cmd (list "seekid" songid
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
2362 (setq time (+ time step)))
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
2363 'mpc-status-refresh)))))
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
2364 (while (mouse-movement-p
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
2365 (event-basic-type (setq event (read-event)))))
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
2366 (cancel-timer timer)))))))
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
2367
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
2368 (defvar mpc--faster-toggle-timer nil)
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
2369 (defun mpc--faster-stop ()
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
2370 (when mpc--faster-toggle-timer
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
2371 (cancel-timer mpc--faster-toggle-timer)
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
2372 (setq mpc--faster-toggle-timer nil)))
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
2373
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
2374 (defun mpc--faster-toggle-refresh ()
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
2375 (if (equal (cdr (assq 'state mpc-status)) "stop")
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
2376 (mpc--faster-stop)))
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
2377
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
2378 (defun mpc--songduration ()
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
2379 (string-to-number
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
2380 (let ((s (cdr (assq 'time mpc-status))))
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
2381 (if (not (string-match ":" s))
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
2382 (error "Unexpected time format %S" s)
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
2383 (substring s (match-end 0))))))
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
2384
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
2385 (defvar mpc--faster-toggle-forward nil)
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
2386 (defvar mpc--faster-acceleration 0.5)
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
2387 (defun mpc--faster-toggle (speedup step)
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
2388 (setq speedup (float speedup))
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
2389 (if mpc--faster-toggle-timer
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
2390 (mpc--faster-stop)
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
2391 (mpc-status-refresh) (mpc-proc-sync)
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
2392 (lexical-let* ((speedup speedup)
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
2393 songid ;The ID of the currently ffwd/rewinding song.
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
2394 songnb ;The position of that song in the playlist.
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
2395 songduration ;The duration of that song.
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
2396 songtime ;The time of the song last time we ran.
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
2397 oldtime ;The timeoftheday last time we ran.
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
2398 prevsongid) ;The song we're in the process leaving.
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
2399 (let ((fun
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
2400 (lambda ()
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
2401 (let ((newsongid (cdr (assq 'songid mpc-status)))
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
2402 (newsongnb (cdr (assq 'song mpc-status))))
|
106354
|
2403
|
106342
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
2404 (if (and (equal prevsongid newsongid)
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
2405 (not (equal prevsongid songid)))
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
2406 ;; We left prevsongid and came back to it. Pretend it
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
2407 ;; didn't happen.
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
2408 (setq newsongid songid))
|
106354
|
2409
|
106342
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
2410 (cond
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
2411 ((null newsongid) (mpc--faster-stop))
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
2412 ((not (equal songid newsongid))
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
2413 ;; We jumped to another song: reset.
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
2414 (setq songid newsongid)
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
2415 (setq songtime (string-to-number
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
2416 (cdr (assq 'time mpc-status))))
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
2417 (setq songduration (mpc--songduration))
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
2418 (setq oldtime (float-time)))
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
2419 ((and (>= songtime songduration) mpc--faster-toggle-forward)
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
2420 ;; Skip to the beginning of the next song.
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
2421 (if (not (equal (cdr (assq 'state mpc-status)) "play"))
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
2422 (mpc-proc-cmd "next" 'mpc-status-refresh)
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
2423 ;; If we're playing, this is done automatically, so we
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
2424 ;; don't need to do anything, or rather we *shouldn't*
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
2425 ;; do anything otherwise there's a race condition where
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
2426 ;; we could skip straight to the next next song.
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
2427 nil))
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
2428 ((and (<= songtime 0) (not mpc--faster-toggle-forward))
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
2429 ;; Skip to the end of the previous song.
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
2430 (setq prevsongid songid)
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
2431 (mpc-proc-cmd "previous"
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
2432 (lambda ()
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
2433 (mpc-status-refresh
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
2434 (lambda ()
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
2435 (setq songid (cdr (assq 'songid mpc-status)))
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
2436 (setq songtime (setq songduration (mpc--songduration)))
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
2437 (setq oldtime (float-time))
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
2438 (mpc-proc-cmd (list "seekid" songid songtime)))))))
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
2439 (t
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
2440 (setq speedup (+ speedup mpc--faster-acceleration))
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
2441 (let ((newstep
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
2442 (truncate (* speedup (- (float-time) oldtime)))))
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
2443 (if (<= newstep 1) (setq newstep 1))
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
2444 (setq oldtime (+ oldtime (/ newstep speedup)))
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
2445 (if (not mpc--faster-toggle-forward)
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
2446 (setq newstep (- newstep)))
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
2447 (setq songtime (min songduration (+ songtime newstep)))
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
2448 (unless (>= songtime songduration)
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
2449 (condition-case nil
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
2450 (mpc-proc-cmd
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
2451 (list "seekid" songid songtime)
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
2452 'mpc-status-refresh)
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
2453 (mpc-proc-error (mpc-status-refresh)))))))
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
2454 (setq songnb newsongnb)))))
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
2455 (setq mpc--faster-toggle-forward (> step 0))
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
2456 (funcall fun) ;Initialize values.
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
2457 (setq mpc--faster-toggle-timer
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
2458 (run-with-timer t 0.3 fun))))))
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
2459
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
2460
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
2461
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
2462 (defvar mpc-faster-speedup 8)
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
2463
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
2464 (defun mpc-ffwd (event)
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
2465 "Fast forward."
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
2466 (interactive (list last-nonmenu-event))
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
2467 ;; (mpc--faster event 4.0 1)
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
2468 (mpc--faster-toggle mpc-faster-speedup 1))
|
106354
|
2469
|
106342
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
2470 (defun mpc-rewind (event)
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
2471 "Fast rewind."
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
2472 (interactive (list last-nonmenu-event))
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
2473 ;; (mpc--faster event 4.0 -1)
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
2474 (mpc--faster-toggle mpc-faster-speedup -1))
|
106354
|
2475
|
|
2476
|
106342
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
2477 (defun mpc-play-at-point (&optional event)
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
2478 (interactive (list last-nonmenu-event))
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
2479 (mpc-select event)
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
2480 (mpc-play))
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
2481
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
2482 ;; (defun mpc-play-tagval ()
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
2483 ;; "Play all the songs of the tag at point."
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
2484 ;; (interactive)
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
2485 ;; (let* ((val (buffer-substring (line-beginning-position) (line-end-position)))
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
2486 ;; (songs (mapcar 'cdar
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
2487 ;; (mpc-proc-buf-to-alists
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
2488 ;; (mpc-proc-cmd (list "find" mpc-tag val))))))
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
2489 ;; (mpc-cmd-add songs)
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
2490 ;; (if (member (cdr (assq 'state (mpc-cmd-status))) '("stop"))
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
2491 ;; (mpc-cmd-play))))
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
2492
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
2493 ;;; Drag'n'drop support ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
2494 ;; Todo:
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
2495 ;; the main thing to do here, is to provide visual feedback during the drag:
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
2496 ;; - change the mouse-cursor.
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
2497 ;; - highlight/select the source and the current destination.
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
2498
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
2499 (defun mpc-drag-n-drop (event)
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
2500 "DWIM for a drag EVENT."
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
2501 (interactive "e")
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
2502 (let* ((start (event-start event))
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
2503 (end (event-end event))
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
2504 (start-buf (window-buffer (posn-window start)))
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
2505 (end-buf (window-buffer (posn-window end)))
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
2506 (songs
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
2507 (with-current-buffer start-buf
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
2508 (goto-char (posn-point start))
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
2509 (if (get-text-property (point) 'mpc-select)
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
2510 ;; FIXME: actually we should only consider the constraints
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
2511 ;; corresponding to the selection in this particular buffer.
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
2512 (mpc-songs-selection)
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
2513 (cond
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
2514 ((and (derived-mode-p 'mpc-songs-mode)
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
2515 (get-text-property (point) 'mpc-file))
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
2516 (list (cons (get-text-property (point) 'mpc-file)
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
2517 (get-text-property (point) 'mpc-file-pos))))
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
2518 ((and mpc-tag (not (mpc-tagbrowser-all-p)))
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
2519 (mapcar (lambda (song)
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
2520 (list (cdr (assq 'file song))))
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
2521 (mpc-cmd-find
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
2522 mpc-tag
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
2523 (buffer-substring (line-beginning-position)
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
2524 (line-end-position)))))
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
2525 (t
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
2526 (error "Unsupported starting position for drag'n'drop gesture")))))))
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
2527 (with-current-buffer end-buf
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
2528 (goto-char (posn-point end))
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
2529 (cond
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
2530 ((eq mpc-tag 'Playlist)
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
2531 ;; Adding elements to a named playlist.
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
2532 (let ((playlist (if (or (mpc-tagbrowser-all-p)
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
2533 (and (bolp) (eolp)))
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
2534 (error "Not a playlist")
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
2535 (buffer-substring (line-beginning-position)
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
2536 (line-end-position)))))
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
2537 (mpc-cmd-add (mapcar 'car songs) playlist)
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
2538 (message "Added %d songs to %s" (length songs) playlist)
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
2539 (if (member playlist
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
2540 (cdr (assq 'Playlist (mpc-constraints-get-current))))
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
2541 (mpc-songs-refresh))))
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
2542 ((derived-mode-p 'mpc-songs-mode)
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
2543 (cond
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
2544 ((null mpc-songs-playlist)
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
2545 (error "The songs shown do not belong to a playlist"))
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
2546 ((eq start-buf end-buf)
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
2547 ;; Moving songs within the shown playlist.
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
2548 (let ((dest-pos (get-text-property (point) 'mpc-file-pos)))
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
2549 (mpc-cmd-move (mapcar 'cdr songs) dest-pos mpc-songs-playlist)
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
2550 (message "Moved %d songs" (length songs))))
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
2551 (t
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
2552 ;; Adding songs to the shown playlist.
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
2553 (let ((dest-pos (get-text-property (point) 'mpc-file-pos))
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
2554 (pl (if (stringp mpc-songs-playlist)
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
2555 (mpc-cmd-find 'Playlist mpc-songs-playlist)
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
2556 (mpc-proc-cmd-to-alist "playlist"))))
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
2557 ;; MPD's protocol does not let us add songs at a particular
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
2558 ;; position in a playlist, so we first have to add them to the
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
2559 ;; end, and then move them to their final destination.
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
2560 (mpc-cmd-add (mapcar 'car songs) mpc-songs-playlist)
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
2561 (mpc-cmd-move (let ((poss '()))
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
2562 (dotimes (i (length songs))
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
2563 (push (+ i (length pl)) poss))
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
2564 (nreverse poss)) dest-pos mpc-songs-playlist)
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
2565 (message "Added %d songs" (length songs)))))
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
2566 (mpc-songs-refresh))
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
2567 (t
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
2568 (error "Unsupported drag'n'drop gesture"))))))
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
2569
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
2570 ;;; Toplevel ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
2571
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
2572 (defcustom mpc-frame-alist '((name . "MPC") (tool-bar-lines . 1)
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
2573 (font . "Sans"))
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
2574 "Alist of frame parameters for the MPC frame."
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
2575 :type 'alist)
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
2576
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
2577 ;;;###autoload
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
2578 (defun mpc ()
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
2579 "Main entry point for MPC."
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
2580 (interactive
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
2581 (progn
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
2582 (if current-prefix-arg
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
2583 (setq mpc-host (read-string "MPD host and port: " nil nil mpc-host)))
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
2584 nil))
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
2585 (let* ((song-buf (mpc-songs-buf))
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
2586 (song-win (get-buffer-window song-buf 0)))
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
2587 (if song-win
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
2588 (select-window song-win)
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
2589 (if (or (window-dedicated-p (selected-window))
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
2590 (window-minibuffer-p))
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
2591 (ignore-errors (select-frame (make-frame mpc-frame-alist)))
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
2592 (with-current-buffer song-buf
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
2593 (set (make-local-variable 'mpc-previous-window-config)
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
2594 (current-window-configuration))))
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
2595 (let* ((win1 (selected-window))
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
2596 (win2 (split-window))
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
2597 (tags mpc-browser-tags))
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
2598 (unless tags (error "Need at least one entry in `mpc-browser-tags'"))
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
2599 (set-window-buffer win2 song-buf)
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
2600 (set-window-dedicated-p win2 'soft)
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
2601 (mpc-status-buffer-show)
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
2602 (while
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
2603 (progn
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
2604 (set-window-buffer win1 (mpc-tagbrowser-buf (pop tags)))
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
2605 (set-window-dedicated-p win1 'soft)
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
2606 tags)
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
2607 (setq win1 (split-window win1 nil 'horiz)))))
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
2608 (balance-windows-area))
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
2609 (mpc-songs-refresh)
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
2610 (mpc-status-refresh))
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
2611
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
2612 (provide 'mpc)
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
2613
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
2614 ;; arch-tag: 4794b2f5-59e6-4f26-b695-650b3e002f37
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
2615 ;;; mpc.el ends here
|