diff -Nru emms-4.4/AUTHORS emms-5.0/AUTHORS --- emms-4.4/AUTHORS 2017-10-20 20:49:00.000000000 +0000 +++ emms-5.0/AUTHORS 2018-05-01 18:43:15.000000000 +0000 @@ -2,6 +2,8 @@ emms. This is necessary to keep track of people who have copyright claims on sources, so please don't be too humble and add yourself. + +Alex Kost Bram van der Kroef Daimrod Damien Elmes @@ -20,6 +22,8 @@ Michael Olson Nick Alcock Petteri Hintsanen +Pierre Neidhardt +stardiviner Tassilo Horn Thierry Volpiatto Trent Buck @@ -29,6 +33,7 @@ Yoni (Johnathan) Rabkin mathias.dahl Rasmus Pank Roulund +ZHANG Weiyi The following is a list of people who contributed trivial patches, diff -Nru emms-4.4/ChangeLog emms-5.0/ChangeLog --- emms-4.4/ChangeLog 2017-10-31 22:15:22.000000000 +0000 +++ emms-5.0/ChangeLog 2018-05-01 18:45:10.000000000 +0000 @@ -1,3 +1,351 @@ +commit cffef39bd9297154b3ed91a68f8fc230e0f87fba +Author: Yoni Rabkin +Date: Tue May 1 14:43:15 2018 -0400 + + bump to version 5.0 + +commit 6740042df600637032dd71794f1b600a85c4099d +Author: ZHANG Weiyi +Date: Wed Apr 18 13:18:35 2018 +0800 + + * lisp/emms-player-mpv.el: Use `emms-player-base-format-list' + +commit 9b7b50a89bc4f9df7f9edd6e939508288f0ffa9b +Author: Yoni Rabkin +Date: Thu Apr 12 09:43:51 2018 -0400 + + * NEWS: + +commit e69e910843594a09d8e337b7724ae2e67cc73f84 +Author: Yoni Rabkin +Date: Thu Apr 12 09:39:55 2018 -0400 + + * lisp/emms-volume-pulse.el: bug fix + + Regexp supported only single digits numbers. Bug fix by Eugene Sharygin. + +commit c90a7535ff1e6552274adf3a48b777316ff8d897 +Author: Pierre Neidhardt +Date: Tue Apr 10 09:51:16 2018 +0530 + + * NEWS: update + +commit 9ca1984fac4843635d512da20243c1556e194ec6 +Author: Pierre Neidhardt +Date: Tue Apr 10 09:39:23 2018 +0530 + + * lisp/emms-browser.el: Fix emms-browser-get-track-field-function custom values + +commit d77202aed79efad2df3b87fc3db3897474da82b7 +Author: Yoni Rabkin +Date: Mon Apr 9 13:46:02 2018 -0400 + + * lisp/emms-player-mpv.el: don't show albums + + Add "--no-audio-display" to the mpv backend by default. + +commit cbfcaeda1f05292994f1725471cb2799664f078e +Author: Pierre Neidhardt +Date: Mon Apr 9 18:10:52 2018 +0530 + + * lisp/emms-browser.el: Make 'emms-browser-move-up-level interactive + + This is useful for Org-style browsing. + +commit 4b7b660acaae68ea1b2945e7a14971bcb37ed0eb +Author: Pierre Neidhardt +Date: Mon Apr 9 18:11:32 2018 +0530 + + * lisp/emms-browser.el: Add 'emms-browser-toggle-subitems-recursively + + It enables Org-style browsing. + +commit 5f0194d5f49aa6ae09e35bfd1f5c816787b106db +Author: Pierre Neidhardt +Date: Mon Apr 9 17:26:09 2018 +0530 + + * lisp/emms-browser.el: Fix missing result in fallback thumbnail filter + +commit ca4a9e559d48bda94311afd17918a92a27c69abd +Author: Pierre Neidhardt +Date: Mon Apr 9 16:13:30 2018 +0530 + + * lisp/emms-cache.el: Add the `emms-cache-reset' function for convenience + + It can be useful sometimes to reset the cache: + + - Whenever too many undesirable tracks have populated the collection, it's + faster to reset and re-add only the desired tracks. + + - Whenever it gets corrupted (it ideally should not...). + +commit d4ba37fcab1ad377319c52a8131de32cf9d306d7 +Author: Pierre Neidhardt +Date: Mon Apr 9 16:03:16 2018 +0530 + + * lisp/emms-browser.el: Support region and prefix arg from emms-browser-remove-tracks + +commit 2bc4236bb1b1cf1605ea155fb8d22c6b2ab06283 +Author: Pierre Neidhardt +Date: Mon Apr 9 15:59:19 2018 +0530 + + * lisp/emms-browser.el: Use albumartist before artist by default + + I believe it to be the most common use-case. For the old behaviour, revert + `emms-browser-get-track-field-function' to 'emms-browser-get-track-field-simple. + +commit c9a5405f2df81f013b76b507d6fab975cb30a318 +Author: Pierre Neidhardt +Date: Mon Apr 9 15:05:56 2018 +0530 + + * lisp/emms-browser.el: Add emms-browser-remove-tracks + + With a prefix argument, remove files and empty folders. + This supersedes emms-browser-delete-files. + +commit 33f2d96ba142f30b3953c57b9d51fac274544623 +Author: Pierre Neidhardt +Date: Mon Apr 9 14:14:56 2018 +0530 + + * lisp/emms-browser.el: Add all tracks in region are with numeric prefix arg + +commit 71b8198b29b02263acd7126179c1710351787796 +Author: Pierre Neidhardt +Date: Mon Apr 9 13:40:07 2018 +0530 + + * lisp/emms-browser.el: Move cursor forward when adding tracks + + It makes it possible to keep pressing to add a sequence of tracks. + +commit 26908fa4ec7725027c996d10373a61e00ff1b935 +Author: Pierre Neidhardt +Date: Mon Apr 9 13:26:17 2018 +0530 + + * lisp/emms-browser.el: Re-use the browser search buffer in emms-smart-browse + + The browser search now acts as a "browser view" until it is killed (e.g. with + "q"). This is probably what the user expects. + + Previously, successive calls to emms-smart-browse from a browser search would + result in cascading window splits of browsers and playlists. + +commit a644af54471869338346f51f62f45303ca5901e8 +Author: Yoni Rabkin +Date: Mon Apr 9 10:35:27 2018 -0400 + + * NEWS: update + + Update the latest of Pierre's work. + +commit a0b351d0572bfe264e23aa3ef8c660be354252e7 +Author: Yoni Rabkin +Date: Mon Apr 9 10:33:03 2018 -0400 + + * AUTHORS: add authors + + Add the authors of emms-player-mpv.el. + +commit 122a8b375b4f5f90de3b41e766442d23c5b2b524 +Author: Pierre Neidhardt +Date: Sat Apr 7 18:53:43 2018 +0530 + + * lisp/later-do.el: Speed up later-do-list job by batch-processing + + A `later-do-batch' defcustom was introduced to allow for performance tweaking. + +commit 283c04e54c080b55f7d044b7eaa54f29356e97da +Author: Pierre Neidhardt +Date: Mon Apr 9 11:49:26 2018 +0530 + + * lisp/emms-player-mpv.el: Add the mpv backend + +commit 58c83cf6c640bc241fb933ce743d1876bbcbba8c +Author: Pierre Neidhardt +Date: Mon Apr 9 11:37:08 2018 +0530 + + * lisp/emms-info-opusinfo.el: Add support for Opus info queries + +commit 949f9b9e5f43be7a9b665f8bbaa7082a238d3336 +Author: Yoni Rabkin +Date: Thu Apr 5 16:59:06 2018 -0400 + + * AUTHORS: minor fix + +commit 84ca32a8562162c3e6001ba54acba139f2023435 +Author: Yoni Rabkin +Date: Tue Apr 3 10:49:11 2018 -0400 + + * NEWS: reword + +commit ffd8c0e8a7649d4e3a0d4f9d65e114346145a2de +Author: Yoni Rabkin +Date: Wed Mar 28 10:58:37 2018 -0400 + + * NEWS: shout out to Pierre + +commit cf361f15912ba27e26cda2796f28aa128cd5a970 +Author: Yoni Rabkin +Date: Wed Mar 28 10:56:35 2018 -0400 + + * NEWS: update + +commit 51fd0927372c63833b998b86174b920def3b172a +Author: Yoni Rabkin +Date: Wed Mar 28 10:53:48 2018 -0400 + + * doc/emms.texinfo: mention mid3v2 + +commit e94ed1cff1513f536c920ed3076319a1021d8842 +Author: Yoni Rabkin +Date: Wed Mar 28 10:50:49 2018 -0400 + + * lisp/emms-tag-editor.el: depreciate mp3info + +commit 7a5da34e1192dd7a32545a7c0edbd9bb69e7922e +Author: Yoni Rabkin +Date: Mon Mar 19 19:09:42 2018 -0400 + + * lisp/emms-tag-editor.el: mid3v2 replaces mp3info + + mp3info only works with 1.x tags. + +commit 0459003a1686b5742e660d08e7c936d1b06e8e7c +Author: Pierre Neidhardt +Date: Sat Feb 17 21:19:35 2018 +0100 + + Set emms-directory according to user-emacs-directory + +commit 3a8d16d91edae81ffb2bb9efa12d41712edfd4f8 +Author: Pierre Neidhardt +Date: Wed Jan 3 14:20:50 2018 +0100 + + Obsolete emms-devel and emms-all + +commit f586070b598b1a19842212686e88df346f1ebc1f +Author: Pierre Neidhardt +Date: Fri Dec 29 22:04:34 2017 +0100 + + Define all mode-maps with defvar instead of defconst + +commit 1ba1707f398b541baee516a9314b1ae1cc2f5bae +Author: Pierre Neidhardt +Date: Fri Dec 29 22:01:32 2017 +0100 + + emms-browser: Add mode hook + +commit 5650f6bbcd05e9759193342a3004af4de252765c +Author: Yoni Rabkin +Date: Fri Dec 29 11:31:48 2017 -0500 + + * lisp/emms-metaplaylist-mode.el: bug fix + + Stop center-on-current interpreting special regexp characters. + +commit f5b2da5876a66b9a7570001feba7dfc06668787b +Author: Pierre Neidhardt +Date: Tue Dec 26 10:13:32 2017 +0100 + + Add Homepage to the package header + +commit de28c9389f1d347e2d6ee7329d6fcb3aac274a28 +Author: Yoni Rabkin +Date: Fri Dec 15 18:05:41 2017 -0500 + + * NEWS: update + +commit 1aa7b6581fa1a99bcd9ee4187a2522033847f64c +Author: Yoni Rabkin +Date: Fri Dec 15 18:02:06 2017 -0500 + + * doc/emms.texinfo: metaplaylist-mode + + Document the changes to metaplaylist-mode. + +commit f268773cae680546f74d2f0a2ff5733b182485ba +Author: Yoni Rabkin +Date: Fri Dec 15 18:01:22 2017 -0500 + + * lisp/emms-metaplaylist-mode.el: re-write. + + This is all but a re-write of metaplaylist mode to make it a more + usable. + +commit 728114cc41bf56fe7f442df48366a66e209e5528 +Author: Yoni Rabkin +Date: Wed Dec 13 17:36:07 2017 -0500 + + * lisp/emms-source-file.el: fix behavior + + This never does the right thing, so let it work like add-directory. + +commit cd53cecbd5a0036de89a373dc71567a9630b33a4 +Author: Pierre Neidhardt +Date: Sat Dec 9 16:44:24 2017 +0100 + + Fix 'seq' requirement in emms-browser + +commit bcad17702f4aea763491efb62551f3f5888cc0b2 +Author: Pierre Neidhardt +Date: Sat Dec 9 16:30:49 2017 +0100 + + AUTHORS: Add Pierre Neidhardt + +commit e70461dd1a1ad09c92a4d1753f94e95abc76eeb2 +Author: Pierre Neidhardt +Date: Sat Dec 9 16:30:01 2017 +0100 + + Document dynamic cover thumbnail caching + +commit d4a75dda9316dfe8ec9dfe7368b226121ad5e898 +Author: Pierre Neidhardt +Date: Sat Dec 9 16:00:36 2017 +0100 + + Add progress reporter to EMMS browser expansion + + The thumbnail display makes expansion even slower because of cache building and + querying. + +commit d8a9539576903c8f06eb87a048b4d9ba7b6a6061 +Author: Pierre Neidhardt +Date: Sun Dec 3 20:01:28 2017 +0100 + + Add support for dynamic thumbnail caching + +commit 0960515e644015c6d85549fa3bef3d67c0ee7116 +Author: Pierre Neidhardt +Date: Sun Nov 26 18:35:44 2017 +0100 + + lisp/emms-browser.el: Extract year from info-date or fallback on info-year + +commit babc32f7079b1a5925b60fa5c9874c9ccbb5c414 +Author: Pierre Neidhardt +Date: Sun Nov 26 18:33:18 2017 +0100 + + lisp/emms-browser.el: Add autoloads to emms-browser and emms-smart-browse + +commit 32db2aff20b784a01c07d1138cb50d25526bcfd9 +Author: Yoni Rabkin +Date: Wed Nov 22 06:59:58 2017 -0500 + + * lisp/emms-player-mpd.el: interactive + + Make `emms-player-mpd-play interactive. + +commit 5e49985e8fcbf5e0c24f0a8690d3d8ba2f0a3838 +Author: Yoni Rabkin +Date: Wed Nov 15 14:49:25 2017 -0500 + + * lisp/emms-browser.el: Remove pitchfork + + Pitchfork is not a desirable resource. See the discussion on the + emms-help mailing list for references. + +commit 11954d51e976a83635971fc000a163b0e7056134 +Author: Yoni Rabkin +Date: Sun Nov 5 08:02:16 2017 -0500 + + Push version updates. + commit 88fecd0234da595843ce6be4d3f9f2b755ff612d Author: Yoni Rabkin Date: Fri Oct 20 16:49:00 2017 -0400 diff -Nru emms-4.4/debian/changelog emms-5.0/debian/changelog --- emms-4.4/debian/changelog 2017-12-13 02:00:50.000000000 +0000 +++ emms-5.0/debian/changelog 2018-05-02 00:39:13.000000000 +0000 @@ -1,3 +1,13 @@ +emms (5.0-1) unstable; urgency=medium + + * New upstream release. + + d/copyright: Update copyright years and holders. + * d/control: + + Bump Standards-Version to 4.1.4. + - Remove Git get-orig-source rule (using tarballs these days anyway). + + -- Arnaud Fontaine Wed, 02 May 2018 09:39:13 +0900 + emms (4.4-1) unstable; urgency=low * New upstream release. diff -Nru emms-4.4/debian/control emms-5.0/debian/control --- emms-4.4/debian/control 2017-12-13 02:00:50.000000000 +0000 +++ emms-5.0/debian/control 2018-05-02 00:39:13.000000000 +0000 @@ -9,7 +9,7 @@ texinfo, libtagc0-dev Homepage: https://www.gnu.org/software/emms/ -Standards-Version: 4.1.2 +Standards-Version: 4.1.4 Package: emms Architecture: any diff -Nru emms-4.4/debian/copyright emms-5.0/debian/copyright --- emms-4.4/debian/copyright 2017-12-13 02:00:50.000000000 +0000 +++ emms-5.0/debian/copyright 2018-05-02 00:39:13.000000000 +0000 @@ -1,15 +1,26 @@ -Format: http://www.debian.org/doc/packaging-manuals/copyright-format/1.0/ +Format: https://www.debian.org/doc/packaging-manuals/copyright-format/1.0/ Upstream-Name: emms Upstream-Contact: emms-help@gnu.org Source: http://www.gnu.org/s/emms/ Files: * -Copyright: 1985-2016 Free Software Foundation, Inc. +Copyright: 2003-2018 Free Software Foundation, Inc. +License: GPL-3+ + +Files: lisp/emms-player-mpv.el +Copyright: 2014, Alex Kost + 2013-2018 ZHANG Weiyi + 2018, Free Software Foundation, Inc. + 2018, stardiviner +License: GPL-3+ + +Files: lisp/emms-playlist-limit.el +Copyright: 2007-2009, William Xu License: GPL-3+ Files: debian/* Copyright: 2004-2007, Jorgen Schaefer - 2007-2016, Arnaud Fontaine + 2007-2018, Arnaud Fontaine License: GPL-3+ License: GPL-3+ diff -Nru emms-4.4/debian/rules emms-5.0/debian/rules --- emms-4.4/debian/rules 2017-12-13 02:00:50.000000000 +0000 +++ emms-5.0/debian/rules 2018-05-02 00:39:13.000000000 +0000 @@ -14,37 +14,3 @@ build/emms:: make -C doc/ all emms.html - -# Generate the upstream tarball from upstream Git (adapted from -# http://wiki.debian.org/SandroTosi/Svn_get-orig-source for Git) -PACKAGE := $(shell dpkg-parsechangelog | \ - sed -ne 's/^Source: \([a-z.]*\).*/\1/p') - -SRC_VERSION := $(shell dpkg-parsechangelog | \ - sed -ne 's/^Version: \([^-]\+\)-.*/\1/p') - -ifneq (,$(findstring git, $(SRC_VERSION))) -GIT_VERSION := $(shell echo $(SRC_VERSION) | \ - sed -ne 's/.*git\([a-z0-9]\+\)/\1/p') -else -GIT_VERSION := $(shell echo $(SRC_VERSION) | \ - sed -ne 's/\([0-9]\+:\)\?\([0-9.]\+\)/\2/p') -endif - -TARBALL = $(PACKAGE)_$(SRC_VERSION).orig.tar.gz - -get-orig-source: - rm -rf get-orig-source ../$(TARBALL) - - git clone git://git.sv.gnu.org/emms.git \ - get-orig-source/ - - cd get-orig-source/ && \ - git archive --prefix=$(PACKAGE)-$(SRC_VERSION).orig/ \ - --format=tar $(GIT_VERSION) `/bin/ls | grep -v master` | \ - gzip --no-name --best > ../../$(TARBALL) - - rm -rf get-orig-source - @echo "'../$(TARBALL)' created." - -.PHONY: get-orig-source diff -Nru emms-4.4/doc/developer-release.txt emms-5.0/doc/developer-release.txt --- emms-4.4/doc/developer-release.txt 2017-10-20 20:49:00.000000000 +0000 +++ emms-5.0/doc/developer-release.txt 2018-05-01 18:43:15.000000000 +0000 @@ -1,10 +1,12 @@ This file tries to list the things people have to do before they do a release. -* Increase the version number in emms.el and Makefile +* Increase the version number in emms.el and Makefile * Update NEWS +* Push version updates to git repo. + * Tag release in VCS, for example `git tag -a 4.2 -m "4.2"' * Push tag to VCS if needed, for example `git push --tags origin "4.2"' diff -Nru emms-4.4/doc/emms.texinfo emms-5.0/doc/emms.texinfo --- emms-4.4/doc/emms.texinfo 2017-10-20 20:49:00.000000000 +0000 +++ emms-5.0/doc/emms.texinfo 2018-05-01 18:43:15.000000000 +0000 @@ -81,6 +81,7 @@ * Streaming Audio:: Interface to streaming audio. * APE / FLAC Commands:: How to play next or previous track in these files. * Bookmarks:: Saving a place in a media file. +* Managing Playlists:: Managing multiple playlists. * GNU FM:: Connect to music community websites. Copying and license @@ -194,16 +195,18 @@ The function @code{emms-default-players} in the last line sets up the list of default players. The list contains lightweight specialized players like ogg123 or mpg321 and we-play-everything-players such as -mplayer, vlc, etc.. To be sure that emms can play all your music you -should check that your preferred players are installed on the machine. +mplayer, mpv, vlc, etc.. To be sure that emms can play all your music +you should check that your preferred players are installed on the +machine. More detail about setting up Emms can be found in the setup chapter, @xref{Setup}. Emms tries to display the tags (the name of the song, as opposed to the name of the file) of the music you listen to. Emms can use libtag, -see @xref{Using TagLib}, or a combination of `mp3info' and `ogginfo' -(make sure that they are installed if you want Emms to use them.) +see @xref{Using TagLib}, or a combination of other software such as +`mp3info', `ogginfo' and `opusinfo' (make sure that they are installed +if you want Emms to use them.) The last thing to do is to tell Emms where your music is; the root directory of our music collection. Let's say all your music is in @@ -873,12 +876,14 @@ @cindex info tags Emms is distributed with multiple predefined methods for retrieving -info, provided by @file{emms-info-mp3info.el}, -@file{emms-info-ogginfo.el}, @file{emms-cue.el} and -@file{emms-info-libtag.el}. The first two packages are front-ends for -command-line tools. Ogg track information is retrieved using the -@uref{http://directory.fsf.org/audio/ogg/vorbistools.html, ogginfo} -software. Likewise, mp3 track information is available using +info, provided by modules such as @file{emms-info-mp3info.el}, +@file{emms-info-ogginfo.el}, @file{emms-info-opusinfo.el}, +@file{emms-cue.el} and @file{emms-info-libtag.el}. The first three +packages are front-ends for command-line tools. Ogg track information is +retrieved using the +@uref{http://directory.fsf.org/audio/ogg/vorbistools.html, ogginfo} and +the @uref{https://www.opus-codec.org/ opusinfo} software. Likewise, mp3 +track information is available using @uref{http://www.ibiblio.org/mp3info/, mp3info}. @file{emms-cue.el} retrieves tracks information for ape/flac files by parsing a cue sheet file, which is plain text. Finally, @file{emms-info-libtag.el} uses a @@ -904,7 +909,8 @@ @defopt emms-info-asynchronously Non-nil when track information should be loaded asynchronously. This requires the feature `later-do' which is provided by the file -@file{later-do.el}, which should come with Emms. +@file{later-do.el}, which comes with Emms. See @var{later-do-batch} for +performance tweaking. @end defopt @defopt emms-info-functions Functions which add information to tracks. Each is called with a @@ -1651,12 +1657,25 @@ @section Displaying Covers The browser will attempt to display cover images if they're -available. By default it looks for images @file{cover_small.jpg}, -@file{cover_med.jpg}, etc. Customize @var{emms-browser-covers} and -@var{emms-browser-covers-file-extensions} to use your own covers. Note -that you'll probably want to resize your existing covers to particular +available. + +Customize @var{emms-browser-covers} to configure how EMMS should retrieve the +covers. + +By default it looks for images @file{cover_small.jpg}, @file{cover_med.jpg}, +etc. Note that you'll probably want to resize your existing covers to particular sizes. Suggested sizes are 100x100 for small, and 200x200 for medium. +The above behaviour demands manual processing on behalf of the user. Instead, +you might prefer to automate the process by setting @var{emms-browser-covers} to +'emms-browser-cache-thumbnail': covers matching 'emms-browser-thumbnail-filter' +will be automatically resized if necessary and cached to +@var{emms-browser-thumbnail-directory}. The cache gets automatically updated +upon change in the source folder. + +Customize @var{emms-browser-covers-file-extensions} to include or exclude +specific extensions. + Also, Emacs by default will jump around a lot when scrolling a buffer with images. In order to prevent that, you can set @var{scroll-up-aggressively} and @var{scroll-down-aggressively} to the @@ -1707,6 +1726,12 @@ (add-hook 'emms-browser-filter-changed-hook 'toggle-album-display) @end lisp +Furthermore, you can customize +@var{emms-browser-get-track-field-function} to choose which the metadata +fields used for the different tree nodes (@code{'info-artist}, +@code{info-year}, etc.). For instance, you can choose whether to +organize the tree by artist, album artist or performer. + @subheading Changing Display Format Format strings govern the way items are displayed in the browser and @@ -1885,7 +1910,7 @@ Using @file{emms-tag-editor.el}, emms can set tag informations of tracks and write them back to the file with the help of external programs, such -as `mp3info', `vorbiscomment'. +as `mid3v2' and `vorbiscomment'. Use the keybinding @kbd{E} to edit the tags of track under point in the playlist or all marked tracks (@pxref{Markable Playlists} for how to @@ -1948,9 +1973,6 @@ @defvr {Variable} emms-tag-editor-tagfile-functions To write tags to track file, an extern program should specified in this variable. - -If the external program has an interface like `mp3info', you don't have -to write a function. Take `mp3' and `ogg' as example. @end defvr @heading Renaming Files @@ -2328,7 +2350,7 @@ `emms-stream-info' calls a backend program to query the stream for information. The preferred program needs to be specified by setting -the variable @var{emms-stream-info-backend} either `mplayer' or +the variable @var{emms-stream-info-backend} either `mplayer', `mpv' or `vlc'. For instance: @lisp @@ -2448,6 +2470,71 @@ @c ------------------------------------------------------------------- +@node Managing Playlists +@chapter Managing Playlists + +Emms can have multiple playlists, since a playlist is just another +buffer with a list of tracks. You can manage multiple playlists using +`emms-metaplaylist-mode', provided by the file +@file{emms-metaplaylist-mode}. + +Start the playlist manager with @kbd{M-x +emms-metaplaylist-mode-go}. The playlist manager will list the +playlists and mark the current one. The following commands are +available: + +@table @kbd + +@item RET +@kindex RET +@findex emms-metaplaylist-mode-goto-current +Make the buffer at point the Emms playlist buffer and switch to it. + +@item SPC +@kindex SPC +@findex emms-metaplaylist-mode-set-active +Make the buffer at point the Emms playlist buffer (but do not switch +to it). + +@item n +@kindex n +@findex next-line +Move point to the next playlist. + +@item p +@kindex p +@findex previous-line +Move point to the previous playlist. + +@item g +@kindex g +@findex emms-metaplaylist-mode-update +Update the playlist manager buffer. + +@item C +@kindex C +@findex emms-metaplaylist-mode-new-buffer +Create a new Emms playlist buffer. + +@item C-k +@kindex C-k +@findex emms-metaplaylist-mode-kill-buffer +Kill the Emms playlist buffer at point. + +@item c +@kindex c +@findex emms-metaplaylist-mode-center-current +Move point to the current playlist buffer. + +@item q +@kindex q +@findex kill-this-buffer +Kill the playlist manager. + +@end table + + +@c ------------------------------------------------------------------- @node GNU FM @chapter GNU FM diff -Nru emms-4.4/lisp/emms-auto.el emms-5.0/lisp/emms-auto.el --- emms-4.4/lisp/emms-auto.el 2017-10-31 22:15:21.000000000 +0000 +++ emms-5.0/lisp/emms-auto.el 2018-05-01 18:45:10.000000000 +0000 @@ -12,8 +12,29 @@ (provide 'emms-auto) ;;; Generated autoloads follow (made by autoload.el). -;;;### (autoloads nil "emms-lyrics" "emms-lyrics.el" (23018 20729 -;;;;;; 605997 181000)) +;;;### (autoloads nil "emms-cache" "emms-cache.el" (23243 42542 768833 +;;;;;; 10000)) +;;; Generated autoloads from emms-cache.el + +(autoload 'emms-cache-enable "emms-cache" "\ +Enable caching of Emms track data. + +\(fn)" t nil) + +(autoload 'emms-cache-disable "emms-cache" "\ +Disable caching of Emms track data. + +\(fn)" t nil) + +(autoload 'emms-cache-toggle "emms-cache" "\ +Toggle caching of Emms track data. + +\(fn)" t nil) + +;;;*** + +;;;### (autoloads nil "emms-lyrics" "emms-lyrics.el" (23066 63019 +;;;;;; 833518 586000)) ;;; Generated autoloads from emms-lyrics.el (autoload 'emms-lyrics-enable "emms-lyrics" "\ @@ -54,8 +75,8 @@ ;;;*** -;;;### (autoloads nil "emms-player-mpd" "emms-player-mpd.el" (23018 -;;;;;; 25073 367692 687000)) +;;;### (autoloads nil "emms-player-mpd" "emms-player-mpd.el" (23066 +;;;;;; 63019 835518 561000)) ;;; Generated autoloads from emms-player-mpd.el (autoload 'emms-player-mpd-clear "emms-player-mpd" "\ @@ -94,7 +115,7 @@ ;;;*** ;;;### (autoloads nil "emms-playing-time" "emms-playing-time.el" -;;;;;; (23018 20729 609997 131000)) +;;;;;; (23066 63019 836518 548000)) ;;; Generated autoloads from emms-playing-time.el (autoload 'emms-playing-time-enable-display "emms-playing-time" "\ @@ -131,7 +152,7 @@ ;;;*** ;;;### (autoloads nil "emms-playlist-mode" "emms-playlist-mode.el" -;;;;;; (23018 20729 610997 118000)) +;;;;;; (23114 37598 734909 572000)) ;;; Generated autoloads from emms-playlist-mode.el (autoload 'emms-playlist-mode "emms-playlist-mode" "\ @@ -163,8 +184,8 @@ ;;;*** -;;;### (autoloads nil "emms-setup" "emms-setup.el" (23018 20729 611997 -;;;;;; 106000)) +;;;### (autoloads nil "emms-setup" "emms-setup.el" (23243 29612 256714 +;;;;;; 62000)) ;;; Generated autoloads from emms-setup.el (autoload 'emms-minimalistic "emms-setup" "\ @@ -197,8 +218,8 @@ ;;;*** -;;;### (autoloads nil "emms-source-file" "emms-source-file.el" (23018 -;;;;;; 20729 612997 93000)) +;;;### (autoloads nil "emms-source-file" "emms-source-file.el" (23091 +;;;;;; 60394 151933 52000)) ;;; Generated autoloads from emms-source-file.el (autoload 'emms-play-file "emms-source-file" nil t) (autoload 'emms-add-file "emms-source-file" nil t) @@ -269,8 +290,8 @@ ;;;*** -;;;### (autoloads nil "emms-volume" "emms-volume.el" (23018 20729 -;;;;;; 615997 56000)) +;;;### (autoloads nil "emms-volume" "emms-volume.el" (23066 63019 +;;;;;; 839518 511000)) ;;; Generated autoloads from emms-volume.el (autoload 'emms-volume-raise "emms-volume" "\ @@ -296,7 +317,7 @@ ;;;*** ;;;### (autoloads nil "emms-volume-amixer" "emms-volume-amixer.el" -;;;;;; (23018 20729 614997 68000)) +;;;;;; (23066 63019 838518 523000)) ;;; Generated autoloads from emms-volume-amixer.el (autoload 'emms-volume-amixer-change "emms-volume-amixer" "\ @@ -307,7 +328,7 @@ ;;;*** ;;;### (autoloads nil "emms-volume-pulse" "emms-volume-pulse.el" -;;;;;; (23018 20729 615997 56000)) +;;;;;; (23247 24987 21680 660000)) ;;; Generated autoloads from emms-volume-pulse.el (autoload 'emms-volume-pulse-change "emms-volume-pulse" "\ @@ -317,36 +338,33 @@ ;;;*** -;;;### (autoloads nil nil ("emms-bookmarks.el" "emms-browser.el" -;;;;;; "emms-compat.el" "emms-cue.el" "emms-history.el" "emms-i18n.el" -;;;;;; "emms-info-libtag.el" "emms-info-metaflac.el" "emms-info-mp3info.el" -;;;;;; "emms-info-ogginfo.el" "emms-info.el" "emms-last-played.el" -;;;;;; "emms-librefm-scrobbler.el" "emms-librefm-stream.el" "emms-maint.el" -;;;;;; "emms-mark.el" "emms-metaplaylist-mode.el" "emms-mode-line-icon.el" -;;;;;; "emms-player-mpg321-remote.el" "emms-player-mplayer.el" "emms-player-simple.el" -;;;;;; "emms-player-vlc.el" "emms-player-xine.el" "emms-playlist-sort.el" -;;;;;; "emms-show-all.el" "emms-stream-info.el" "emms-tag-editor.el" -;;;;;; "emms-url.el" "emms.el" "jack.el" "later-do.el") (23032 62831 -;;;;;; 732081 711000)) +;;;### (autoloads nil nil ("emms-bookmarks.el" "emms-compat.el" "emms-cue.el" +;;;;;; "emms-history.el" "emms-i18n.el" "emms-info-libtag.el" "emms-info-metaflac.el" +;;;;;; "emms-info-mp3info.el" "emms-info-ogginfo.el" "emms-info-opusinfo.el" +;;;;;; "emms-info.el" "emms-last-played.el" "emms-librefm-scrobbler.el" +;;;;;; "emms-librefm-stream.el" "emms-maint.el" "emms-mark.el" "emms-metaplaylist-mode.el" +;;;;;; "emms-mode-line-icon.el" "emms-player-mpg321-remote.el" "emms-player-mplayer.el" +;;;;;; "emms-player-mpv.el" "emms-player-simple.el" "emms-player-vlc.el" +;;;;;; "emms-player-xine.el" "emms-playlist-sort.el" "emms-show-all.el" +;;;;;; "emms-stream-info.el" "emms-tag-editor.el" "emms-url.el" +;;;;;; "emms.el" "jack.el" "later-do.el") (23272 46328 130081 844000)) ;;;*** -;;;### (autoloads nil "emms-cache" "emms-cache.el" (21273 53744 557869 -;;;;;; 0)) -;;; Generated autoloads from emms-cache.el - -(autoload 'emms-cache-enable "emms-cache" "\ -Enable caching of Emms track data. +;;;### (autoloads nil "emms-browser" "emms-browser.el" (23247 24921 +;;;;;; 337354 949000)) +;;; Generated autoloads from emms-browser.el -\(fn)" t nil) - -(autoload 'emms-cache-disable "emms-cache" "\ -Disable caching of Emms track data. +(autoload 'emms-browser "emms-browser" "\ +Launch or switch to the EMMS Browser. \(fn)" t nil) -(autoload 'emms-cache-toggle "emms-cache" "\ -Toggle caching of Emms track data. +(autoload 'emms-smart-browse "emms-browser" "\ +Display browser and playlist. +Toggle between selecting browser, playlist or hiding both. Tries +to behave sanely if the user has manually changed the window +configuration. \(fn)" t nil) diff -Nru emms-4.4/lisp/emms-browser.el emms-5.0/lisp/emms-browser.el --- emms-4.4/lisp/emms-browser.el 2017-10-20 20:49:00.000000000 +0000 +++ emms-5.0/lisp/emms-browser.el 2018-05-01 18:43:15.000000000 +0000 @@ -61,6 +61,7 @@ ;; C-j emms-browser-add-tracks-and-play ;; RET emms-browser-add-tracks ;; SPC emms-browser-toggle-subitems +;; ^ emms-browser-move-up-level ;; / emms-isearch-buffer ;; 1 emms-browser-collapse-all ;; 2 emms-browser-expand-to-level-2 @@ -96,16 +97,12 @@ ;; b 5 emms-browse-by-composer ;; b 6 emms-browse-by-performer -;; W a p emms-browser-lookup-album-on-pitchfork ;; W a w emms-browser-lookup-album-on-wikipedia -;; W A p emms-browser-lookup-artist-on-pitchfork ;; W A w emms-browser-lookup-artist-on-wikipedia -;; W C p emms-browser-lookup-composer-on-pitchfork ;; W C w emms-browser-lookup-composer-on-wikipedia -;; W P p emms-browser-lookup-performer-on-pitchfork ;; W P w emms-browser-lookup-performer-on-wikipedia ;; Displaying covers @@ -292,12 +289,16 @@ (require 'emms-source-file) (require 'emms-playlist-sort) (require 'sort) +(require 'seq) ;; -------------------------------------------------- ;; Variables and configuration ;; -------------------------------------------------- +(defvar emms-browser-mode-hook nil + "Emms browser mode hook.") + (defgroup emms-browser nil "*The Emacs Multimedia System browser" :prefix "emms-browser-" @@ -319,7 +320,7 @@ :type 'function) (defcustom emms-browser-get-track-field-function - 'emms-browser-get-track-field-simple + 'emms-browser-get-track-field-albumartist "*A function to get an element from a track. Change this to customize the way data is organized in the browser. For example, @@ -328,7 +329,8 @@ soundtracks, compilations and so on don't populate the artist view with lots of 1-track elements." :group 'emms-browser - :type 'function) + :type '(choice (function :tag "Sort by album-artist" emms-browser-get-track-field-albumartist) + (function :tag "Simple" emms-browser-get-track-field-simple))) (defcustom emms-browser-covers '("cover_small" "cover_med" "cover_large") @@ -424,6 +426,9 @@ (defvar emms-browser-buffer-name "*EMMS Browser*" "The default buffer name.") +(defvar emms-browser-search-buffer-name "*emms-browser-search*" + "The search buffer name.") + (defvar emms-browser-top-level-hash nil "The current mapping db, eg. artist -> track.") (make-variable-buffer-local 'emms-browser-top-level-hash) @@ -438,7 +443,7 @@ (defvar emms-browser-current-filter-name nil "The name of the current filter in place, if any.") -(defconst emms-browser-mode-map +(defvar emms-browser-mode-map (let ((map (make-sparse-keymap))) (define-key map (kbd "q") 'emms-browser-bury-buffer) (define-key map (kbd "/") 'emms-isearch-buffer) @@ -449,6 +454,7 @@ (define-key map (kbd "?") 'describe-mode) (define-key map (kbd "C-/") 'emms-playlist-mode-undo) (define-key map (kbd "SPC") 'emms-browser-toggle-subitems) + (define-key map (kbd "^") 'emms-browser-move-up-level) (define-key map (kbd "RET") 'emms-browser-add-tracks) (define-key map (kbd "") 'emms-browser-add-tracks-and-play) (define-key map (kbd "C-j") 'emms-browser-add-tracks-and-play) @@ -474,13 +480,9 @@ (define-key map (kbd "s t") 'emms-browser-search-by-title) (define-key map (kbd "s s") 'emms-browser-search-by-names) (define-key map (kbd "W A w") 'emms-browser-lookup-artist-on-wikipedia) - (define-key map (kbd "W A p") 'emms-browser-lookup-artist-on-pitchfork) (define-key map (kbd "W C w") 'emms-browser-lookup-composer-on-wikipedia) - (define-key map (kbd "W C p") 'emms-browser-lookup-composer-on-pitchfork) (define-key map (kbd "W P w") 'emms-browser-lookup-performer-on-wikipedia) - (define-key map (kbd "W P p") 'emms-browser-lookup-performer-on-pitchfork) (define-key map (kbd "W a w") 'emms-browser-lookup-album-on-wikipedia) - (define-key map (kbd "W a p") 'emms-browser-lookup-album-on-pitchfork) (define-key map (kbd ">") 'emms-browser-next-filter) (define-key map (kbd "<") 'emms-browser-previous-filter) (define-key map (kbd "+") 'emms-volume-raise) @@ -488,7 +490,7 @@ map) "Keymap for `emms-browser-mode'.") -(defconst emms-browser-search-mode-map +(defvar emms-browser-search-mode-map (let ((map (make-sparse-keymap))) (set-keymap-parent map emms-browser-mode-map) (define-key map (kbd "q") 'emms-browser-kill-search) @@ -517,6 +519,7 @@ ;; General mode setup ;; -------------------------------------------------- +;;;###autoload (defun emms-browser () "Launch or switch to the EMMS Browser." (interactive) @@ -559,7 +562,9 @@ (setq buffer-read-only t) (unless no-update - (setq emms-browser-buffer (current-buffer)))) + (setq emms-browser-buffer (current-buffer))) + + (run-hooks 'emms-browser-mode-hook)) (defun emms-browser-new-buffer () "Create a new browser buffer, and switch to it." @@ -577,10 +582,12 @@ (emms-browser-create)))) (defun emms-browser-get-buffer () - "Return the current buffer if it exists, or nil." - (unless (or (null emms-browser-buffer) - (not (buffer-live-p emms-browser-buffer))) - emms-browser-buffer)) + "Return the current buffer if it exists, or nil. +If a browser search exists, return it." + (or (get-buffer emms-browser-search-buffer-name) + (unless (or (null emms-browser-buffer) + (not (buffer-live-p emms-browser-buffer))) + emms-browser-buffer))) (defun emms-browser-ensure-browser-buffer () (unless (eq major-mode 'emms-browser-mode) @@ -641,8 +648,30 @@ (funcall emms-browser-get-track-field-function track type)) (defun emms-browser-get-track-field-simple (track type) + "Return TYPE from TRACK without any heuristic. +This function can be used as +`emms-browser-get-track-field-function'." (emms-track-get track type "misc")) +(defun emms-browser-get-track-field-albumartist (track type) + "Return TYPE from TRACK with an albumartist-oriented heuristic. +For 'info-artist TYPE, use 'info-albumartistsort, 'info-albumartist, +'info-artistsort. +For 'info-year TYPE, use 'info-originalyear, 'info-originaldate and +'info-date symbols." + (cond ((eq type 'info-artist) + (or (emms-track-get track 'info-albumartistsort) + (emms-track-get track 'info-albumartist) + (emms-track-get track 'info-artistsort) + (emms-track-get track 'info-artist ""))) + ((eq type 'info-year) + (let ((date (or (emms-track-get track 'info-originaldate) + (emms-track-get track 'info-originalyear) + (emms-track-get track 'info-date) + (emms-track-get track 'info-year "")))) + (emms-format-date-to-year date))) + (t (emms-track-get track type "misc")))) + (defun emms-browser-get-track-field-use-directory-name (track type) (if (eq type 'info-artist) (emms-browser-get-artist-from-path @@ -819,7 +848,7 @@ (defun emms-browser-year-number (track) "Return a string representation of a track's year. This will be in the form '(1998) '." - (let ((year (emms-track-get track 'info-year))) + (let ((year (emms-track-get-year track))) (if (or (not (stringp year)) (string= year "0")) "" (concat @@ -1048,14 +1077,15 @@ "Move up one level if possible. Return true if we were able to move up. If DIRECTION is 1, move forward, otherwise move backwards." + (interactive "P") (let ((moved nil) (continue t) (current-level (emms-browser-level-at-point))) (while (and continue (zerop (forward-line - (or direction -1)))) - (when (> current-level (emms-browser-level-at-point)) + (or (and (numberp direction) direction) -1)))) + (when (> current-level (or (emms-browser-level-at-point) 0)) (setq moved t) (setq continue nil))) moved)) @@ -1070,6 +1100,23 @@ (cl-assert (emms-browser-move-up-level)) (emms-browser-kill-subitems)))) +(defun emms-browser-toggle-subitems-recursively () + "Recursively toggle all subitems under the current line. +If there is no more subitems to expand, collapse the current node." + (interactive) + (let ((current-level (emms-browser-level-at-point)) + first-expandable-level) + (save-excursion + (while (or (and (emms-browser-subitems-exist) + (not (emms-browser-subitems-visible)) + (or (and (not first-expandable-level) + (setq first-expandable-level (emms-browser-level-at-point))) + (= first-expandable-level (emms-browser-level-at-point))) + (emms-browser-show-subitems)) + (emms-browser-find-entry-more-than-level current-level)))) + (unless first-expandable-level + (emms-browser-kill-subitems)))) + (defun emms-browser-show-subitems () "Show subitems under the current line." (unless (emms-browser-subitems-visible) @@ -1142,13 +1189,28 @@ (defun emms-browser-expand-to-level (level) "Expand to a depth specified by LEVEL. After expanding, jump to the currently marked entry." - (goto-char (point-min)) - (while (not (eq (buffer-end 1) (point))) - (if (< (emms-browser-level-at-point) level) - (emms-browser-show-subitems)) - (emms-browser-next-non-track)) - (emms-browser-pop-mark) - (recenter '(4))) + (let ((count 1) + (total 0) + progress-reporter) + (goto-char (point-min)) + (while (not (eq (buffer-end 1) (point))) + (when (= (emms-browser-level-at-point) 1) + (setq total (1+ total))) + (emms-browser-next-non-track)) + (goto-char (point-min)) + (setq progress-reporter + (make-progress-reporter "Expanding EMMS browser entries..." + 0 total)) + (while (not (eq (buffer-end 1) (point))) + (when (= (emms-browser-level-at-point) 1) + (progress-reporter-update progress-reporter count) + (setq count (1+ count))) + (if (< (emms-browser-level-at-point) level) + (emms-browser-show-subitems)) + (emms-browser-next-non-track)) + (progress-reporter-done progress-reporter) + (emms-browser-pop-mark) + (recenter '(4)))) (defun emms-browser-mark-and-collapse () "Save the current top level element, and collapse." @@ -1229,16 +1291,29 @@ ;; User-visible commands ;; -------------------------------------------------- -(defun emms-browser-add-tracks () - "Add all tracks at point. -Return the previous point-max before adding." - (interactive) - (let ((first-new-track (with-current-emms-playlist (point-max))) - (bdata (emms-browser-bdata-at-point))) - (emms-browser-playlist-insert-bdata - bdata (emms-browser-bdata-level bdata)) +(defun emms-browser-add-tracks (&optional start end) + "Add all tracks at point or in region if active. +When the region is not active, a numeric prefix argument inserts that many +tracks from point. +Return the playlist buffer point-max before adding." + (interactive "r") + (let ((count (cond + ((use-region-p) + (1+ (- (line-number-at-pos end) (line-number-at-pos start)))) + ((numberp current-prefix-arg) + current-prefix-arg) + (t 1))) + (first-new-track (with-current-emms-playlist (point-max)))) + (when (use-region-p) (goto-char start)) + (dotimes (_ count first-new-track) + (let ((bdata (emms-browser-bdata-at-point))) + (when bdata + (emms-browser-playlist-insert-bdata + bdata (emms-browser-bdata-level bdata)) + (forward-line)))) (run-hook-with-args 'emms-browser-tracks-added-hook first-new-track) + (deactivate-mark) first-new-track)) (defun emms-browser-add-tracks-and-play () @@ -1334,32 +1409,58 @@ (emms-browser-view-in-dired (car (emms-browser-bdata-data bdata)))) (emms-browser-view-in-dired (emms-browser-bdata-at-point)))) -(defun emms-browser-delete-files () - "Delete all files under point. -Disabled by default." - (interactive) - (let ((tracks (emms-browser-tracks-at-point)) - dirs path) - (unless (yes-or-no-p - (format "Really permanently delete these %d tracks? " - (length tracks))) - (error "Cancelled!")) - (message "Deleting files..") - (dolist (track tracks) - (setq path (emms-track-get track 'name)) - (delete-file path) - (add-to-list 'dirs (file-name-directory path)) - (emms-cache-del path)) +(defun emms-browser-remove-tracks (&optional delete start end) + "Remove all tracks at point or in region if active. +Unless DELETE is non-nil or with prefix argument, this only acts on the browser, +files are untouched. +If caching is enabled, files are removed from the cache as well. +When the region is not active, a numeric prefix argument remove that many +tracks from point, it does not delete files." + (interactive "P\nr") + (let ((count (cond + ((use-region-p) + (1+ (- (line-number-at-pos end) (line-number-at-pos start)))) + ((numberp current-prefix-arg) + current-prefix-arg) + (t 1))) + dirs path tracks) + ;; If numeric prefix argument, never delete files. + (when (numberp delete) (setq delete nil)) + (when delete + (save-mark-and-excursion + (when (use-region-p) (goto-char start)) + (let ((lines (min count (- (line-number-at-pos (point-max)) (line-number-at-pos (point)))))) + (dotimes (_ lines) + ;; TODO: Test this! + (setq tracks (append tracks (emms-browser-tracks-at-point))) + (forward-line)))) + (unless (yes-or-no-p + (format "Really permanently delete these %d tracks? " (length tracks))) + (error "Cancelled!")) + (message "Deleting files...")) + (when (use-region-p) (goto-char start)) + (dotimes (_ count) + (dolist (track (emms-browser-tracks-at-point)) + (setq path (emms-track-get track 'name)) + (when delete + (delete-file path)) + (add-to-list 'dirs (file-name-directory path)) + (emms-cache-del path)) + ;; remove the item from the browser + (when (emms-browser-tracks-at-point) + (emms-browser-delete-current-node))) + (deactivate-mark) ;; remove empty dirs - (dolist (dir dirs) - (run-hook-with-args 'emms-browser-delete-files-hook dir tracks) - (condition-case nil - (delete-directory dir) - (error nil))) - ;; remove the item from the browser - (emms-browser-delete-current-node) - (message "Deleting files..done"))) + (when delete + (dolist (dir dirs) + (run-hook-with-args 'emms-browser-delete-files-hook dir tracks) + (condition-case nil + (delete-directory dir) + (error nil)))) + (when delete + (message "Deleting files...done")))) +(defalias 'emms-browser-delete-files 'emms-browser-remove-tracks) (put 'emms-browser-delete-files 'disabled t) (defun emms-browser-clear-playlist () @@ -1380,10 +1481,6 @@ (emms-browser-lookup field "http://en.wikipedia.org/wiki/Special:Search?search=")) -(defun emms-browser-lookup-pitchfork (field) - (emms-browser-lookup - field "http://www.pitchforkmedia.com/search/record_reviews/query?query[keywords]=")) - (defun emms-browser-lookup-artist-on-wikipedia () (interactive) (emms-browser-lookup-wikipedia 'info-artist)) @@ -1400,21 +1497,6 @@ (interactive) (emms-browser-lookup-wikipedia 'info-album)) -(defun emms-browser-lookup-artist-on-pitchfork () - (interactive) - (emms-browser-lookup-pitchfork 'info-artist)) - -(defun emms-browser-lookup-composer-on-pitchfork () - (interactive) - (emms-browser-lookup-pitchfork 'info-composer)) - -(defun emms-browser-lookup-performer-on-pitchfork () - (interactive) - (emms-browser-lookup-pitchfork 'info-performer)) - -(defun emms-browser-lookup-album-on-pitchfork () - (interactive) - (emms-browser-lookup-pitchfork 'info-album)) ;; -------------------------------------------------- ;; Linked browser and playlist windows @@ -1426,6 +1508,7 @@ :group 'emms-browser :type 'boolean) +;;;###autoload (defun emms-smart-browse () "Display browser and playlist. Toggle between selecting browser, playlist or hiding both. Tries @@ -1467,7 +1550,13 @@ (if wind (progn (select-window wind) - (emms-browser-bury-buffer)) + (emms-browser-bury-buffer) + ;; After a browser search, the following buffer could be the + ;; unfiltered browser, which we want to bury as well. We don't want + ;; to call `emms-browser-hide-display-hook' for this one so we bury it + ;; directly. + (when (eq major-mode 'emms-browser-mode) + (bury-buffer))) ;; otherwise bury both (bury-buffer) (emms-browser-hide-linked-window))) @@ -1481,7 +1570,7 @@ ((eq major-mode 'emms-browser-mode) (car (emms-playlist-buffer-list))) ((eq major-mode 'emms-playlist-mode) - emms-browser-buffer))) + (emms-browser-get-buffer)))) (defun emms-browser-get-linked-window () "Return linked window (eg browser if playlist is selected." @@ -1562,7 +1651,7 @@ (defun emms-browser-search-buffer-go () "Create a new search buffer, or clean the existing one." (switch-to-buffer - (get-buffer-create "*emms-browser-search*")) + (get-buffer-create emms-browser-search-buffer-name)) (emms-browser-mode t) (use-local-map emms-browser-search-mode-map) (emms-with-inhibit-read-only-t @@ -1625,7 +1714,7 @@ (defun emms-browser--build-cover-filename () "Build `emms-browser--covers-filename'. -Based on from `emms-browser-covers' and +Based on from `emms-browser-covers' (when a list) and `emms-browser-covers-file-extensions'." (setq emms-browser--covers-filename (mapcar (lambda (cover) @@ -1644,8 +1733,6 @@ (defun emms-browser-get-cover-from-path (path &optional size) "Return a cover filename, if it exists." - (unless emms-browser--covers-filename - (emms-browser--build-cover-filename)) (unless size (setq size 'medium)) (let* ((size-idx (cond @@ -1658,6 +1745,8 @@ (funcall emms-browser-covers (file-name-directory path) size)) ((and (listp emms-browser-covers) (nth size-idx emms-browser-covers)) + (unless emms-browser--covers-filename + (emms-browser--build-cover-filename)) (car (delq nil (mapcar (lambda (cover) (let ((coverpath @@ -1744,7 +1833,7 @@ (format-choices `(("i" . ,indent) ("n" . ,name) - ("y" . ,(emms-track-get track 'info-year)) + ("y" . ,(emms-track-get-year track)) ("A" . ,(emms-track-get track 'info-album)) ("a" . ,(emms-track-get track 'info-artist)) ("C" . ,(emms-track-get track 'info-composer)) @@ -2022,5 +2111,120 @@ (emms-track-get track 'last-played nil)) (time-less-p min-date last-played)))))) +;; TODO: Add function to clear the cache from thumbnails that have no associated +;; cover folders. This is especially useful in case the music library path +;; changes: currently, all covers will have to be re-cached while the old ones +;; are left as is, useless. + +;; TODO: `emms-browser-expand-all' is slow because of all the covers (about 30 +;; sec fot 1500 covers in my case). Try to profile & optimize. It will +;; probably not be enough and we might need to run emms-browser-expand-all +;; asynchronously. + + +(defvar emms-browser-thumbnail-directory (expand-file-name "thumbnails" emms-directory) + "Directory where to store cover thumbnails.") + +(defvar emms-browser-thumbnail-small-size 128 + "Cover thumbnail will be resized if necessary so that neither width nor height exceed this dimension.") +(defvar emms-browser-thumbnail-medium-size 256 + "Cover thumbnail will be resized if necessary so that neither width nor height exceed this dimension.") +(defvar emms-browser-thumbnail-large-size 1024 ; Emms does not use large covers as of 2017-11-26. + "Cover thumbnail will be resized if necessary so that neither width nor height exceed this dimension.") + +(defun emms-browser-thumbnail-filter-default (dir) + "Select covers containing 'front' or 'cover' in DIR. +If none was found, fallback on `emms-browser-thumbnail-filter-all'. + +See `emms-browser-thumbnail-filter'." + (when (file-directory-p dir) + (let ((ls (directory-files dir t nil t)) + (case-fold-search t) + covers) + (dolist (ext emms-browser-covers-file-extensions) + (setq covers (append (seq-filter (lambda (c) (string-match (concat "\\(front\\|cover\\).*\\." ext) c)) ls) covers))) + (unless covers + (setq covers (emms-browser-thumbnail-filter-all dir))) + covers))) + +(defun emms-browser-thumbnail-filter-all (dir) + "Return the list of all files with `emms-browser-covers-file-extensions' in DIR. + +See `emms-browser-thumbnail-filter'." + (let (covers) + (dolist (ext emms-browser-covers-file-extensions covers) + (setq covers (append (file-expand-wildcards (expand-file-name (concat "*." ext) dir)) covers))))) + +(defvar emms-browser-thumbnail-filter 'emms-browser-thumbnail-filter-default + "This filter must hold a function that takes a directory argument and returns a list of cover file names. +The list will be processed by `emms-browser-cache-thumbnail'. +See also `emms-browser-thumbnail-filter-default'.") + +(defvar emms-browser-thumbnail-convert-program (executable-find "convert") + "The ImageMagick's `convert' program.") + +(defun emms-browser-cache-thumbnail (dir size) + "Return cached cover SIZE for album in DIR. + +SIZE must be 'small, 'medium or 'large. It will determine the +resolution of the cached file. See the variables +`emms-browser-thumbnail-SIZE-size'. + +If cover is not cached or if cache is out-of-date, re-cache it. +If both the width and the height of the cover are smaller than +`emms-browser-thumbnail-SIZE-size', it need not be cached and +will be used directly. + +Emms assumes that you have one album per folder. This function +will always use the same cover per folder. + +`emms-browser-covers' can be `fset' to this function." + (if (eq size 'large) + ;; 'large is unused for now. Return empty. + nil + (let (covers + cover + (cover-width 0) (cover-height 0) + (size-value (symbol-value (intern (concat "emms-browser-thumbnail-" (symbol-name size) "-size")))) + cache-dest-file) + (setq covers (funcall emms-browser-thumbnail-filter dir)) + (if (not covers) + nil + ;; Find best quality cover. + (let (res) + (dolist (c covers) + (setq res (image-size (create-image c) t)) + ;; image-size does not error, it returns (30 . 30) instead. + (and (> (car res) 30) (> (cdr res) 30) + (< cover-width (car res)) (< cover-height (cdr res)) + (setq cover-width (car res) cover-height (cdr res) cover c)))) + (if (and (>= size-value cover-width) (>= size-value cover-height)) + ;; No need to resize and cache. + cover + (let ((cache-dest (concat emms-browser-thumbnail-directory (file-name-directory cover)))) + (mkdir cache-dest t) + (setq cache-dest-file (concat + (expand-file-name "cover_" cache-dest) + (symbol-name size) + "." (file-name-extension cover)))) + (and emms-browser-thumbnail-convert-program + (or (not (file-exists-p cache-dest-file)) + (time-less-p (nth 5 (file-attributes cache-dest-file)) + (nth 5 (file-attributes cover)) )) + (let (err msg) + ;; An Elisp function would be faster, but Emacs does not seem be be + ;; able to resize image files. It can resize image displays though. + ;; TODO: Add image resizing support to Emacs. + (setq msg (with-output-to-string + (with-current-buffer standard-output + (setq err (call-process (executable-find "convert") nil '(t t) nil + "-resize" (format "%sx%s" size-value size-value) + cover + cache-dest-file))))) + (when (/= err 0) + (warn "%s" msg) + (setq cache-dest-file nil)))) + cache-dest-file))))) + (provide 'emms-browser) ;;; emms-browser.el ends here diff -Nru emms-4.4/lisp/emms-cache.el emms-5.0/lisp/emms-cache.el --- emms-4.4/lisp/emms-cache.el 2017-10-20 20:49:00.000000000 +0000 +++ emms-5.0/lisp/emms-cache.el 2018-05-01 18:43:15.000000000 +0000 @@ -179,5 +179,17 @@ (setq emms-cache-dirty t))) (message "Syncing emms track cache...done")) +(defun emms-cache-reset () + "Reset the cache." + (interactive) + (when (yes-or-no-p "Really reset the cache?") + (setq emms-cache-db + (make-hash-table + :test (if (fboundp 'define-hash-table-test) + 'string-hash + 'equal))) + (setq emms-cache-dirty t) + (emms-cache-save))) + (provide 'emms-cache) ;;; emms-cache.el ends here diff -Nru emms-4.4/lisp/emms.el emms-5.0/lisp/emms.el --- emms-4.4/lisp/emms.el 2017-10-20 20:49:00.000000000 +0000 +++ emms-5.0/lisp/emms.el 2018-05-01 18:43:15.000000000 +0000 @@ -6,6 +6,7 @@ ;; Author: Jorgen Schäfer ;; Keywords: emms, mp3, mpeg, multimedia ;; Package-Requires: ((cl-lib "0.5")) +;; Homepage: http://www.gnu.org/software/emms/ ;; This file is part of EMMS. @@ -41,7 +42,7 @@ ;;; Code: -(defvar emms-version "4.3" +(defvar emms-version "5.0" "EMMS version string.") @@ -284,7 +285,7 @@ :group 'emms :type 'function) -(defcustom emms-directory "~/.emacs.d/emms" +(defcustom emms-directory (expand-file-name "emms" user-emacs-directory) "*Directory variable from which all other emms file variables are derived." :group 'emms :type 'string) @@ -705,6 +706,29 @@ desc (emms-track-simple-description track)))) +(defun emms-track-get-year (track) + "Get year of TRACK for display. +There is the separation between the 'release date' and the +'original date'. This difference matters e.g. for +re-releases (anniversaries and such) where the release date is +more recent than the original release date. In such cases the +user probably wants the original release date so this is what we +show." + (or + (emms-format-date-to-year (emms-track-get track 'info-date)) + (emms-format-date-to-year (emms-track-get track 'info-originaldate)) + (emms-track-get track 'info-year) + (emms-track-get track 'info-originalyear))) + +(defun emms-format-date-to-year (date) + "Try to extract year part from DATE. +Return nil if the year cannot be extracted." + (when date + (let ((year (nth 5 (parse-time-string date)))) + (if year (number-to-string year) + (when (string-match "^[ \t]*\\([0-9]\\{4\\}\\)" date) + (match-string 1 date)))))) + ;;; The Playlist diff -Nru emms-4.4/lisp/emms-info-opusinfo.el emms-5.0/lisp/emms-info-opusinfo.el --- emms-4.4/lisp/emms-info-opusinfo.el 1970-01-01 00:00:00.000000000 +0000 +++ emms-5.0/lisp/emms-info-opusinfo.el 2018-05-01 18:43:15.000000000 +0000 @@ -0,0 +1,85 @@ +;;; emms-info-opusinfo.el --- Emms information from Ogg Opus files. + +;; Copyright (C) 2018 Free Software Foundation, Inc. + +;; Author: Pierre Neidhardt + +;; This file is part of EMMS. + +;; EMMS is free software; you can redistribute it and/or modify it +;; under the terms of the GNU General Public License as published by +;; the Free Software Foundation; either version 3 of the License, or +;; (at your option) any later version. + +;; EMMS is distributed in the hope that it will be useful, +;; but WITHOUT ANY WARRANTY; without even the implied warranty of +;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +;; GNU General Public License for more details. + +;; You should have received a copy of the GNU General Public License +;; along with EMMS; if not, write to the Free Software Foundation, +;; Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA. + +;;; Commentary: +;; + +;;; Code: + +(require 'emms-info) + +(defgroup emms-info-opusinfo nil + "An EMMS-info method for getting, using the external opusinfo +program" + :group 'emms-info) + +(defcustom emms-info-opusinfo-coding-system 'utf-8 + "*Coding system used in the output of opusinfo." + :type 'coding-system + :group 'emms-info-opusinfo) + +(defcustom emms-info-opusinfo-program-name "opusinfo" + "*The name/path of the opusinfo tag program." + :type 'string + :group 'emms-info-opusinfo) + +(defun emms-info-opusinfo (track) + "Add track information to TRACK. +This is a useful element for `emms-info-functions'." + (when (and (eq 'file (emms-track-type track)) + (or (string-match "\\.[Oo][Gg][Gg]\\'" (emms-track-name track)) + (string-match "\\.[Oo][Pp][Uu][Ss]\\'" (emms-track-name track)))) + + (with-temp-buffer + (call-process emms-info-opusinfo-program-name + nil t nil (emms-track-name track)) + + ;; play time + (goto-char (point-min)) + (when (re-search-forward + "Playback length: \\([0-9]*\\)m:\\([0-9]*\\)" nil t) + (let* ((minutes (string-to-number (match-string 1))) + (seconds (string-to-number (match-string 2))) + (ptime-total (+ (* minutes 60) seconds)) + (ptime-min minutes) + (ptime-sec seconds)) + (emms-track-set track 'info-playing-time ptime-total) + (emms-track-set track 'info-playing-time-min ptime-min) + (emms-track-set track 'info-playing-time-sec ptime-sec) + (emms-track-set track 'info-file (emms-track-name track)))) + + ;; all the rest of the info available + (goto-char (point-min)) + (when (re-search-forward "^.*\\.\\.\\.$" (point-max) t) + (while (zerop (forward-line 1)) + (when (looking-at "^\t\\(.*?\\)=\\(.*\\)$") ; recognize the first '=' + (let ((a (match-string 1)) + (b (match-string 2))) + (when (and (< 0 (length a)) + (< 0 (length b))) + (emms-track-set track + (intern (downcase (concat "info-" (match-string 1)))) + (match-string 2)))))))))) + +(provide 'emms-info-opusinfo) + +;;; emms-info-opusinfo.el ends here diff -Nru emms-4.4/lisp/emms-mark.el emms-5.0/lisp/emms-mark.el --- emms-4.4/lisp/emms-mark.el 2017-10-20 20:49:00.000000000 +0000 +++ emms-5.0/lisp/emms-mark.el 2018-05-01 18:43:15.000000000 +0000 @@ -238,7 +238,7 @@ ;;}}} ;;{{{ mode stuff -(defconst emms-mark-mode-map +(defvar emms-mark-mode-map (let ((map (make-sparse-keymap))) (define-key map "W" 'emms-mark-copy-marked-tracks) (define-key map "K" 'emms-mark-kill-marked-tracks) diff -Nru emms-4.4/lisp/emms-metaplaylist-mode.el emms-5.0/lisp/emms-metaplaylist-mode.el --- emms-4.4/lisp/emms-metaplaylist-mode.el 2017-10-20 20:49:00.000000000 +0000 +++ emms-5.0/lisp/emms-metaplaylist-mode.el 2018-05-01 18:43:15.000000000 +0000 @@ -1,6 +1,6 @@ ;;; emms-metaplaylist-mode.el --- A major mode for lists of Emms playlists -;; Copyright (C) 2006, 2007, 2008, 2009 Free Software Foundation, Inc. +;; Copyright (C) 2006, 2007, 2008, 2009, 2017 Free Software Foundation, Inc. ;; Author: Yoni Rabkin @@ -42,7 +42,7 @@ :prefix "emms-metaplaylist-mode-" :group 'multimedia) -(defcustom emms-metaplaylist-mode-buffer-name "*Emms Playlists*" +(defcustom emms-metaplaylist-mode-buffer-name "*Emms Playlist Buffers*" "*Name of the buffer in which Emms playlists will be listed." :type 'string :group 'emms-metaplaylist-mode) @@ -78,16 +78,19 @@ ;;; Keymap ;;; -------------------------------------------------------- -(defconst emms-metaplaylist-mode-map +(defvar emms-metaplaylist-mode-map (let ((map (make-sparse-keymap))) (set-keymap-parent map text-mode-map) - (define-key map (kbd "n") 'next-line) - (define-key map (kbd "p") 'previous-line) + (define-key map (kbd "n") 'next-line) + (define-key map (kbd "p") 'previous-line) (define-key map (kbd "RET") 'emms-metaplaylist-mode-goto-current) - (define-key map (kbd "q") 'kill-this-buffer) - (define-key map (kbd "?") 'describe-mode) - (define-key map (kbd "SPC") 'emms-metaplaylist-set-active) - (define-key map (kbd "c") 'emms-metaplaylist-new-buffer) + (define-key map (kbd "SPC") 'emms-metaplaylist-mode-set-active) + (define-key map (kbd "g") 'emms-metaplaylist-mode-update) + (define-key map (kbd "C") 'emms-metaplaylist-mode-new-buffer) + (define-key map (kbd "C-k") 'emms-metaplaylist-mode-kill-buffer) + (define-key map (kbd "c") 'emms-metaplaylist-mode-center-current) + (define-key map (kbd "q") 'kill-this-buffer) + (define-key map (kbd "?") 'describe-mode) map) "Keymap for `emms-metaplaylist-mode'.") @@ -98,62 +101,115 @@ (defun emms-metaplaylist-mode-goto-current () "Switch to the buffer at point." (interactive) - (switch-to-buffer - (buffer-substring (point-at-bol) - (point-at-eol)))) - -;; Since there will never be a significantly large amount of playlist -;; buffers co-existing at once, we allow ourselves not to keep -;; state. We regenerate the playlists buffer anew on demand. + (let ((buffer (get-buffer + (buffer-substring (point-at-bol) + (point-at-eol))))) + (emms-playlist-set-playlist-buffer buffer) + (switch-to-buffer buffer))) + +(defun emms-metaplaylist-mode-write (playlists) + "Print the sorted list of PLAYLISTS." + (delete-region (point-min) (point-max)) + (mapc (lambda (buf) + (let ((inhibit-read-only t)) + (insert (buffer-name buf)) + (add-text-properties + (point-at-bol) (point-at-eol) + (list 'face + (if (eq buf emms-playlist-buffer) + 'emms-metaplaylist-mode-current-face + 'emms-metaplaylist-mode-face))) + (newline))) + playlists)) + +;; Emms' list changes order, and that's OK, but we want something +;; stable for display purposes. +(defun emms-metaplaylist-mode-sorted-buffer-list () + "Return a sorted list of playlist buffers." + (sort + (copy-tree + (emms-playlist-buffer-list)) + #'(lambda (a b) + (string< (buffer-name a) + (buffer-name b))))) + +(defun emms-metaplaylist-mode-center-current () + "Center on the current playlist buffer" + (interactive) + (when (not emms-playlist-buffer) + (error "no current playlist buffer")) + (goto-char (point-min)) + (when (not + (search-forward-regexp (regexp-quote + (buffer-name emms-playlist-buffer)) + (point-max) t)) + (error "cannot not find the current playlist buffer")) + (goto-char (point-at-bol))) + (defun emms-metaplaylist-mode-create () - "Create or recreate the meta-playlist buffer." + "Create the meta-playlist buffer." (let ((name emms-metaplaylist-mode-buffer-name) - (playlists (emms-playlist-buffer-list))) + (playlists (emms-metaplaylist-mode-sorted-buffer-list))) (if playlists - (progn - (condition-case nil - (kill-buffer name) - (error nil)) - (get-buffer-create name) - (with-current-buffer name - (emms-metaplaylist-mode) - (save-excursion - (mapc (lambda (buf) - (let ((inhibit-read-only t)) - (insert (buffer-name buf)) - (add-text-properties - (point-at-bol) (point-at-eol) - (list 'face - (if (eq buf emms-playlist-buffer) - 'emms-metaplaylist-mode-current-face - 'emms-metaplaylist-mode-face))) - (newline))) - playlists)) - (current-buffer))) ; return the buffer as lisp obj + (with-current-buffer (get-buffer-create name) + (emms-metaplaylist-mode) + (emms-metaplaylist-mode-write playlists) + (emms-metaplaylist-mode-center-current) + (current-buffer)) (error "No Emms playlist buffers")))) +(defun emms-metaplaylist-mode-assert-buffer () + "Assert that we are in the metaplaylist mode buffer." + (when (not (eq (current-buffer) + (get-buffer emms-metaplaylist-mode-buffer-name))) + (error "not the metalplaylist buffer"))) + +(defun emms-metaplaylist-mode-update () + "Update the metalplaylist display." + (interactive) + (emms-metaplaylist-mode-assert-buffer) + (let ((inhibit-read-only t)) + (emms-metaplaylist-mode-write + (emms-metaplaylist-mode-sorted-buffer-list))) + (emms-metaplaylist-mode-center-current)) + +(defun emms-metaplaylist-mode-kill-buffer () + "Kill the buffer at point" + (interactive) + (let ((buffer (get-buffer + (buffer-substring (point-at-bol) + (point-at-eol))))) + (when (not buffer) + (error "can't find buffer at point")) + (if (y-or-n-p (format "kill playlist buffer \"%s\"?" + (buffer-name buffer))) + (kill-buffer buffer) + (message "Buffer kill aborted.")) + (emms-metaplaylist-mode-update))) + + ;;; -------------------------------------------------------- -;;; Playlist Management : creation, deletion (?) +;;; Playlist Management ;;; -------------------------------------------------------- -(defun emms-metaplaylist-new-buffer (buffer-name) - "Creates a new buffer called buffer-name, which will be ready -to host EMMS tracks." +(defun emms-metaplaylist-mode-new-buffer (buffer-name) + "Creates a new buffer playlist buffer BUFFER-NAME." (interactive "sBuffer Name: ") - (if(get-buffer buffer-name) + (if (get-buffer buffer-name) (error "Buffer must not exist.") (let ((buf (get-buffer-create buffer-name))) (with-current-buffer buf - (setq emms-playlist-buffer-p t))) - (message "Buffer created"))) + (emms-playlist-mode) + (setq emms-playlist-buffer-p t))) + (emms-metaplaylist-mode-update))) -(defun emms-metaplaylist-set-active () +(defun emms-metaplaylist-mode-set-active () + "Set the buffer at point to be the active playlist." (interactive) (emms-playlist-set-playlist-buffer (get-buffer (buffer-substring (point-at-bol) (point-at-eol)))) - (let ((ici (point))) - (emms-metaplaylist-mode-go) - (goto-char ici))) + (emms-metaplaylist-mode-update)) + ;;; -------------------------------------------------------- ;;; Mode entry @@ -162,12 +218,16 @@ (defun emms-metaplaylist-mode-go () "Single entry point to the metaplaylist interface." (interactive) - (emms-metaplaylist-mode-create) - (switch-to-buffer emms-metaplaylist-mode-buffer-name)) + (let ((mpm-buffer (get-buffer emms-metaplaylist-mode-buffer-name))) + (if mpm-buffer + (with-current-buffer mpm-buffer + (emms-metaplaylist-mode-update)) + (setq mpm-buffer (emms-metaplaylist-mode-create))) + (switch-to-buffer mpm-buffer))) (defun emms-metaplaylist-mode () "A major mode for Emms playlists." -;; (interactive) + ;; (interactive) (kill-all-local-variables) (use-local-map emms-metaplaylist-mode-map) diff -Nru emms-4.4/lisp/emms-player-mpd.el emms-5.0/lisp/emms-player-mpd.el --- emms-4.4/lisp/emms-player-mpd.el 2017-10-20 20:49:00.000000000 +0000 +++ emms-5.0/lisp/emms-player-mpd.el 2018-05-01 18:43:15.000000000 +0000 @@ -870,6 +870,7 @@ "Play whatever is in the current MusicPD playlist. If ID is specified, play the song at that position in the MusicPD playlist." + (interactive) (if id (progn (unless (stringp id) diff -Nru emms-4.4/lisp/emms-player-mpv.el emms-5.0/lisp/emms-player-mpv.el --- emms-4.4/lisp/emms-player-mpv.el 1970-01-01 00:00:00.000000000 +0000 +++ emms-5.0/lisp/emms-player-mpv.el 2018-05-01 18:43:15.000000000 +0000 @@ -0,0 +1,124 @@ +;;; emms-player-mpv.el --- mpv support for EMMS + +;; Copyright (C) 2013-2018 ZHANG Weiyi +;; Copyright (C) 2014 Alex Kost +;; Copyright (C) 2018 stardiviner +;; Copyright (C) 2018 Free Software Foundation, Inc. + +;; Authors: ZHANG Weiyi , +;; Alex Kost , +;; stardiviner + +;; This file is part of EMMS. + +;; EMMS is free software; you can redistribute it and/or +;; modify it under the terms of the GNU General Public License +;; as published by the Free Software Foundation; either version 3 +;; of the License, or (at your option) any later version. + +;; EMMS is distributed in the hope that it will be useful, +;; but WITHOUT ANY WARRANTY; without even the implied warranty of +;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +;; GNU General Public License for more details. + +;; You should have received a copy of the GNU General Public License +;; along with EMMS; if not, write to the Free Software Foundation, +;; Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA. + +;;; Commentary: + +;; This provides a player that uses mpv. It supports pause and +;; seeking. See mpv manual for more. +;; +;; To load subtitles automatically, +;; put "`sub-auto=fuzzy"` in the mpv's config file. +;; +;; To disable/enable the cover display when playing music, modify +;; `emms-player-mpv-parameters'. For example: (add-to-list +;; 'emms-player-mpv-parameters "--no-audio-display") Alternatively +;; you can also add "audio-display=no" to mpv's config file. +;; +;; This file is based on `emms-player-mplayer.el'. It was originally hosted at +;; https://github.com/dochang/emms-player-mpv. + +;;; Code: + +(require 'emms-compat) +(require 'emms-player-simple) + +(defcustom emms-player-mpv-input-file + (expand-file-name (locate-user-emacs-file "emms-mpv-input-file")) + "The file to send command to mpv." + :type 'file + :group 'emms) + +(define-emms-simple-player mpv '(file url streamlist playlist) + (concat "\\`\\(https?\\|mms\\)://\\|" + (apply #'emms-player-simple-regexp + emms-player-base-format-list)) + "mpv" "--no-audio-display" "--quiet" "--really-quiet") + +(defadvice emms-player-mpv-start (around append-arguments activate) + (unless (file-exists-p emms-player-mpv-input-file) + (call-process "mkfifo" nil nil nil emms-player-mpv-input-file)) + (let* ((input-file (format "--input-file=%s" emms-player-mpv-input-file)) + (track-arg (let* ((track (ad-get-arg 0)) + (track-type (emms-track-get track 'type)) + (track-name (emms-track-name track))) + (if (memq track-type '(streamlist playlist)) + (format "--playlist=%s" track-name) + track-name))) + (process (apply 'start-process + emms-player-simple-process-name + nil + emms-player-mpv-command-name + (append emms-player-mpv-parameters + (list input-file track-arg))))) + (set-process-sentinel process 'emms-player-simple-sentinel)) + (emms-player-started emms-player-mpv)) + +(emms-player-set emms-player-mpv + 'pause + 'emms-player-mpv-pause) + +(emms-player-set emms-player-mpv + 'resume + 'emms-player-mpv-resume) + +(emms-player-set emms-player-mpv + 'seek + 'emms-player-mpv-seek) + +(emms-player-set emms-player-mpv + 'seek-to + 'emms-player-mpv-seek-to) + +(defun emms-player-mpv--format-command (fmt &rest args) + "Generate shell command to control mpv." + (let ((mpv-cmd (apply 'format fmt args))) + (format "echo %s > %s" + (shell-quote-argument mpv-cmd) + (shell-quote-argument emms-player-mpv-input-file)))) + +(defun emms-player-mpv-pause () + "Depends on mpv's --input-file option." + (let ((cmd (emms-player-mpv--format-command "set pause yes"))) + (call-process-shell-command cmd nil nil nil))) + +(defun emms-player-mpv-resume () + "Depends on mpv's --input-file option." + (let ((cmd (emms-player-mpv--format-command "set pause no"))) + (call-process-shell-command cmd nil nil nil))) + +(defun emms-player-mpv-seek (sec) + "Depends on mpv's --input-file option." + (let ((cmd (emms-player-mpv--format-command "seek %d" sec))) + (call-process-shell-command cmd nil nil nil))) + +(defun emms-player-mpv-seek-to (sec) + "Depends on mpv's --input-file option." + (let ((cmd (emms-player-mpv--format-command "seek %d absolute" sec))) + (call-process-shell-command cmd nil nil nil))) + +(provide 'emms-player-mpv) +;;; emms-player-mpv.el ends here diff -Nru emms-4.4/lisp/emms-playlist-mode.el emms-5.0/lisp/emms-playlist-mode.el --- emms-4.4/lisp/emms-playlist-mode.el 2017-10-20 20:49:00.000000000 +0000 +++ emms-5.0/lisp/emms-playlist-mode.el 2018-05-01 18:43:15.000000000 +0000 @@ -112,7 +112,7 @@ ;;; Keys ;;; -------------------------------------------------------- -(defconst emms-playlist-mode-map +(defvar emms-playlist-mode-map (let ((map (make-sparse-keymap))) (set-keymap-parent map text-mode-map) (define-key map (kbd "C-x C-s") 'emms-playlist-save) diff -Nru emms-4.4/lisp/emms-setup.el emms-5.0/lisp/emms-setup.el --- emms-4.4/lisp/emms-setup.el 2017-10-20 20:49:00.000000000 +0000 +++ emms-5.0/lisp/emms-setup.el 2018-05-01 18:43:15.000000000 +0000 @@ -52,6 +52,7 @@ emms-player-ogg123 emms-player-mplayer-playlist emms-player-mplayer + emms-player-mpv emms-player-vlc emms-player-vlc-playlist) "*Default list of players for emms-setup." @@ -66,6 +67,7 @@ (require 'emms-source-playlist) (require 'emms-player-simple) (require 'emms-player-mplayer) + (require 'emms-player-mpv) (require 'emms-player-vlc)) ;;;###autoload @@ -81,6 +83,7 @@ (require 'emms-info) (require 'emms-info-mp3info) (require 'emms-info-ogginfo) + (require 'emms-info-opusinfo) (require 'emms-cache) (require 'emms-mode-line) (require 'emms-mark) @@ -113,6 +116,8 @@ (add-to-list 'emms-info-functions 'emms-info-mp3info)) (when (executable-find emms-info-ogginfo-program-name) (add-to-list 'emms-info-functions 'emms-info-ogginfo)) + (when (executable-find emms-info-opusinfo-program-name) + (add-to-list 'emms-info-functions 'emms-info-opusinfo)) (setq emms-track-description-function 'emms-info-track-description) (when (fboundp 'emms-cache) ; work around compiler warning (emms-cache 1)) @@ -139,10 +144,12 @@ ;;;###autoload (defun emms-devel () (emms-all)) +(make-obsolete 'emms-devel 'emms-all "4.1") ;;;###autoload (defun emms-standard () (emms-all)) +(make-obsolete 'emms-standard 'emms-all "4.1") (provide 'emms-setup) diff -Nru emms-4.4/lisp/emms-show-all.el emms-5.0/lisp/emms-show-all.el --- emms-4.4/lisp/emms-show-all.el 2017-10-20 20:49:00.000000000 +0000 +++ emms-5.0/lisp/emms-show-all.el 2018-05-01 18:43:15.000000000 +0000 @@ -45,7 +45,7 @@ "Major mode for `emms-show-all' \\{emms-show-all-mode-map}") -(defconst emms-show-all-mode-map +(defvar emms-show-all-mode-map (let ((map (make-sparse-keymap))) (set-keymap-parent map text-mode-map) (define-key map (kbd "q") 'emms-show-all-mode-bury-buffer) diff -Nru emms-4.4/lisp/emms-source-file.el emms-5.0/lisp/emms-source-file.el --- emms-4.4/lisp/emms-source-file.el 2017-10-20 20:49:00.000000000 +0000 +++ emms-5.0/lisp/emms-source-file.el 2018-05-01 18:43:15.000000000 +0000 @@ -104,8 +104,7 @@ (interactive (list (read-file-name "Play file: " emms-source-file-default-directory emms-source-file-default-directory - t - (thing-at-point 'filename)))) + t))) (if (file-directory-p file) (emms-source-directory file) (emms-playlist-insert-track diff -Nru emms-4.4/lisp/emms-tag-editor.el emms-5.0/lisp/emms-tag-editor.el --- emms-4.4/lisp/emms-tag-editor.el 2017-10-20 20:49:00.000000000 +0000 +++ emms-5.0/lisp/emms-tag-editor.el 2018-05-01 18:43:15.000000000 +0000 @@ -117,11 +117,11 @@ See also `emms-tag-editor-default-parser'.") (defvar emms-tag-editor-tagfile-functions - '(("mp3" "mp3info" + '(("mp3" "mid3v2" ((info-artist . "a") (info-title . "t") - (info-album . "l") - (info-tracknumber . "n") + (info-album . "A") + (info-tracknumber . "T") (info-year . "y") (info-genre . "g") (info-note . "c"))) @@ -129,7 +129,7 @@ ("flac" . emms-tag-editor-tag-flac)) "An alist used when committing changes to tags in files. If the external program sets tags by command line options -one-by-one such as mp3info, then the list should like: +one-by-one, then the list should like: (EXTENSION PROGRAM COMMAND_LINE_OPTIONS) Otherwise, a function that accepts a single parameter, the track, @@ -625,7 +625,7 @@ (dolist (tag emms-tag-editor-tags) (when (setq val (emms-track-get track (car tag))) (emms-track-set old (car tag) val))) - ;; use mp3info to change tag in mp3 file + ;; use external program to change tags in the file (when (and (eq (emms-track-get track 'type) 'file) (file-writable-p (emms-track-name track)) (setq func (assoc (file-name-extension filename) diff -Nru emms-4.4/lisp/emms-volume-pulse.el emms-5.0/lisp/emms-volume-pulse.el --- emms-4.4/lisp/emms-volume-pulse.el 2017-10-20 20:49:00.000000000 +0000 +++ emms-5.0/lisp/emms-volume-pulse.el 2018-05-01 18:43:15.000000000 +0000 @@ -80,7 +80,7 @@ (cl-loop while (string-match (mapconcat 'identity - '(".*Sink[ \t]+\\#\\([0-9]\\)" + '(".*Sink[ \t]+\\#\\([0-9]+\\)" ".*Name:[ \t]\\([^\n]+\\)" ".*Volume:.*?\\([0-9]+\\)%.*\n?") "\n") diff -Nru emms-4.4/lisp/later-do.el emms-5.0/lisp/later-do.el --- emms-4.4/lisp/later-do.el 2017-10-20 20:49:00.000000000 +0000 +++ emms-5.0/lisp/later-do.el 2018-05-01 18:43:15.000000000 +0000 @@ -1,7 +1,7 @@ ;;; later-do.el --- execute lisp code ... later ;; Copyright (C) 2004, 2005, 2006, 2007, 2008, -;; 2009 Free Software Foundation, Inc. +;; 2009, 2018 Free Software Foundation, Inc. ;; Author: Jorgen Schaefer @@ -28,7 +28,7 @@ ;;; Code: -(defvar later-do-version "0.2emms2 (2005-09-20)" +(defvar later-do-version "0.2emms4 (2018-04-07)" "Version string of later-do.") (defgroup later-do nil @@ -41,6 +41,14 @@ :group 'later-do :type 'number) +(defcustom later-do-batch 20 + "How many functions to process before waiting `later-do-interval'. +The functions are processed from `later-do-list'. Must be 1 or +greater. Too high a value might make Emacs slower while the +list is being processed." + :group 'later-do + :type 'number) + (defvar later-do-list nil "A list of functions to be called later on.") @@ -63,14 +71,16 @@ empty." (if (null later-do-list) (setq later-do-timer nil) - (let ((fun (caar later-do-list)) - (args (cdar later-do-list))) - (setq later-do-list (cdr later-do-list)) + (let (res) (unwind-protect - (apply fun args) - (setq later-do-timer (run-with-timer later-do-interval - nil - 'later-do-timer)))))) + (dotimes (b (min later-do-batch (length later-do-list)) res) + (let ((fun (caar later-do-list)) + (args (cdar later-do-list))) + (setq later-do-list (cdr later-do-list)) + (setq res (apply fun args))))) + (setq later-do-timer (run-with-timer later-do-interval + nil + 'later-do-timer))))) (provide 'later-do) ;;; later-do.el ends here diff -Nru emms-4.4/Makefile emms-5.0/Makefile --- emms-4.4/Makefile 2017-10-20 20:49:00.000000000 +0000 +++ emms-5.0/Makefile 2018-05-01 18:43:15.000000000 +0000 @@ -20,7 +20,7 @@ CHANGELOG_CMD = git log --pretty=medium --no-merges # The currently released version of EMMS -VERSION=4.3 +VERSION=5.0 .PHONY: all install lisp docs deb-install clean .PRECIOUS: %.elc diff -Nru emms-4.4/NEWS emms-5.0/NEWS --- emms-4.4/NEWS 2017-10-20 20:49:00.000000000 +0000 +++ emms-5.0/NEWS 2018-05-01 18:43:15.000000000 +0000 @@ -1,3 +1,29 @@ +News since version 5.0 + + + +News since version 4.4 + + - Add Org-style "TAB" binding to cycle through the different levels of expansions. + - Bind emms-browser-move-up-level to "^". + - Make "RET" (emms-add-tracks) add all tracks in region or with numeric argument + that many tracks. + - Supersede emms-browser-delete-files with emms-browser-remove-tracks to + remove tracks from browser without deleting files. Use prefix argument to + get the old behaviour. Regions and numeric argument are supported. + - Add emms-cache-reset. + - Use the "album artist" instead of the "artist" browser node by default. + - Bug fix: emms-volume-pulse multi-digit volume numbers. + - Bug fix: emms-smart-browse "cascading" from a browser search. + - Bug fix: fix fallback thumbnail filter. + - Add mpv backend support. + - Speed up info processing. + - Add Opus info support via emms-info-opusinfo.el. + - Code modernizations thanks to Pierre Neidhardt. + - Tagging mp3 files v2.x files now works via mid3v2. + - Add dynamic thumbnail caching. + - Improve emms-metaplaylist-mode. + News since version 4.3: - emms-volume-amixer.el: card id can be customized