emms-6.00/0000775000175000017500000000000013746064010010577 5ustar yrkyrkemms-6.00/AUTHORS0000664000175000017500000000355513746063641011670 0ustar yrkyrkThis file lists all people who contributed more than a few lines to 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 Bruno Félix R. Ribeiro Daimrod Damien Elmes Daniel Brockman Daniel Dehennin David Engster Jean-Philippe Theberge Jorgen Schaefer Jose Antonio Ortega Ruiz Lawrence Mitchell Lucas Bonnet Mario Domgörgen Mario Lang Martin Schoenmakers Matthew Kennedy Michael Olson Nick Alcock Petteri Hintsanen Pierre Neidhardt stardiviner Tassilo Horn Thierry Volpiatto Trent Buck Ulrik Jensen William Xu Ye Wenbin Yoni (Johnathan) Rabkin mathias.dahl Rasmus Pank Roulund ZHANG Weiyi Mike Kazantsev Fran Burstall The following is a list of people who contributed trivial patches, which is to say very simple patches and those with total of 12 lines or fewer. We started recording trivial patches this way in June of 2017, so trivial patches before that date would not appear below. David Michael tumashu Maxim Cournoyer Ian Dunn ;; Local variables: ;; coding: utf-8 ;; End: emms-6.00/COPYING0000664000175000017500000010451313746063641011647 0ustar yrkyrk GNU GENERAL PUBLIC LICENSE Version 3, 29 June 2007 Copyright (C) 2007 Free Software Foundation, Inc. Everyone is permitted to copy and distribute verbatim copies of this license document, but changing it is not allowed. Preamble The GNU General Public License is a free, copyleft license for software and other kinds of works. The licenses for most software and other practical works are designed to take away your freedom to share and change the works. By contrast, the GNU General Public License is intended to guarantee your freedom to share and change all versions of a program--to make sure it remains free software for all its users. We, the Free Software Foundation, use the GNU General Public License for most of our software; it applies also to any other work released this way by its authors. You can apply it to your programs, too. When we speak of free software, we are referring to freedom, not price. Our General Public Licenses are designed to make sure that you have the freedom to distribute copies of free software (and charge for them if you wish), that you receive source code or can get it if you want it, that you can change the software or use pieces of it in new free programs, and that you know you can do these things. To protect your rights, we need to prevent others from denying you these rights or asking you to surrender the rights. Therefore, you have certain responsibilities if you distribute copies of the software, or if you modify it: responsibilities to respect the freedom of others. For example, if you distribute copies of such a program, whether gratis or for a fee, you must pass on to the recipients the same freedoms that you received. You must make sure that they, too, receive or can get the source code. And you must show them these terms so they know their rights. Developers that use the GNU GPL protect your rights with two steps: (1) assert copyright on the software, and (2) offer you this License giving you legal permission to copy, distribute and/or modify it. For the developers' and authors' protection, the GPL clearly explains that there is no warranty for this free software. For both users' and authors' sake, the GPL requires that modified versions be marked as changed, so that their problems will not be attributed erroneously to authors of previous versions. Some devices are designed to deny users access to install or run modified versions of the software inside them, although the manufacturer can do so. This is fundamentally incompatible with the aim of protecting users' freedom to change the software. The systematic pattern of such abuse occurs in the area of products for individuals to use, which is precisely where it is most unacceptable. Therefore, we have designed this version of the GPL to prohibit the practice for those products. If such problems arise substantially in other domains, we stand ready to extend this provision to those domains in future versions of the GPL, as needed to protect the freedom of users. Finally, every program is threatened constantly by software patents. States should not allow patents to restrict development and use of software on general-purpose computers, but in those that do, we wish to avoid the special danger that patents applied to a free program could make it effectively proprietary. To prevent this, the GPL assures that patents cannot be used to render the program non-free. The precise terms and conditions for copying, distribution and modification follow. TERMS AND CONDITIONS 0. Definitions. "This License" refers to version 3 of the GNU General Public License. "Copyright" also means copyright-like laws that apply to other kinds of works, such as semiconductor masks. "The Program" refers to any copyrightable work licensed under this License. Each licensee is addressed as "you". "Licensees" and "recipients" may be individuals or organizations. To "modify" a work means to copy from or adapt all or part of the work in a fashion requiring copyright permission, other than the making of an exact copy. The resulting work is called a "modified version" of the earlier work or a work "based on" the earlier work. A "covered work" means either the unmodified Program or a work based on the Program. To "propagate" a work means to do anything with it that, without permission, would make you directly or secondarily liable for infringement under applicable copyright law, except executing it on a computer or modifying a private copy. Propagation includes copying, distribution (with or without modification), making available to the public, and in some countries other activities as well. To "convey" a work means any kind of propagation that enables other parties to make or receive copies. Mere interaction with a user through a computer network, with no transfer of a copy, is not conveying. An interactive user interface displays "Appropriate Legal Notices" to the extent that it includes a convenient and prominently visible feature that (1) displays an appropriate copyright notice, and (2) tells the user that there is no warranty for the work (except to the extent that warranties are provided), that licensees may convey the work under this License, and how to view a copy of this License. If the interface presents a list of user commands or options, such as a menu, a prominent item in the list meets this criterion. 1. Source Code. The "source code" for a work means the preferred form of the work for making modifications to it. "Object code" means any non-source form of a work. A "Standard Interface" means an interface that either is an official standard defined by a recognized standards body, or, in the case of interfaces specified for a particular programming language, one that is widely used among developers working in that language. The "System Libraries" of an executable work include anything, other than the work as a whole, that (a) is included in the normal form of packaging a Major Component, but which is not part of that Major Component, and (b) serves only to enable use of the work with that Major Component, or to implement a Standard Interface for which an implementation is available to the public in source code form. A "Major Component", in this context, means a major essential component (kernel, window system, and so on) of the specific operating system (if any) on which the executable work runs, or a compiler used to produce the work, or an object code interpreter used to run it. The "Corresponding Source" for a work in object code form means all the source code needed to generate, install, and (for an executable work) run the object code and to modify the work, including scripts to control those activities. However, it does not include the work's System Libraries, or general-purpose tools or generally available free programs which are used unmodified in performing those activities but which are not part of the work. For example, Corresponding Source includes interface definition files associated with source files for the work, and the source code for shared libraries and dynamically linked subprograms that the work is specifically designed to require, such as by intimate data communication or control flow between those subprograms and other parts of the work. The Corresponding Source need not include anything that users can regenerate automatically from other parts of the Corresponding Source. The Corresponding Source for a work in source code form is that same work. 2. Basic Permissions. All rights granted under this License are granted for the term of copyright on the Program, and are irrevocable provided the stated conditions are met. This License explicitly affirms your unlimited permission to run the unmodified Program. The output from running a covered work is covered by this License only if the output, given its content, constitutes a covered work. This License acknowledges your rights of fair use or other equivalent, as provided by copyright law. You may make, run and propagate covered works that you do not convey, without conditions so long as your license otherwise remains in force. You may convey covered works to others for the sole purpose of having them make modifications exclusively for you, or provide you with facilities for running those works, provided that you comply with the terms of this License in conveying all material for which you do not control copyright. Those thus making or running the covered works for you must do so exclusively on your behalf, under your direction and control, on terms that prohibit them from making any copies of your copyrighted material outside their relationship with you. Conveying under any other circumstances is permitted solely under the conditions stated below. Sublicensing is not allowed; section 10 makes it unnecessary. 3. Protecting Users' Legal Rights From Anti-Circumvention Law. No covered work shall be deemed part of an effective technological measure under any applicable law fulfilling obligations under article 11 of the WIPO copyright treaty adopted on 20 December 1996, or similar laws prohibiting or restricting circumvention of such measures. When you convey a covered work, you waive any legal power to forbid circumvention of technological measures to the extent such circumvention is effected by exercising rights under this License with respect to the covered work, and you disclaim any intention to limit operation or modification of the work as a means of enforcing, against the work's users, your or third parties' legal rights to forbid circumvention of technological measures. 4. Conveying Verbatim Copies. You may convey verbatim copies of the Program's source code as you receive it, in any medium, provided that you conspicuously and appropriately publish on each copy an appropriate copyright notice; keep intact all notices stating that this License and any non-permissive terms added in accord with section 7 apply to the code; keep intact all notices of the absence of any warranty; and give all recipients a copy of this License along with the Program. You may charge any price or no price for each copy that you convey, and you may offer support or warranty protection for a fee. 5. Conveying Modified Source Versions. You may convey a work based on the Program, or the modifications to produce it from the Program, in the form of source code under the terms of section 4, provided that you also meet all of these conditions: a) The work must carry prominent notices stating that you modified it, and giving a relevant date. b) The work must carry prominent notices stating that it is released under this License and any conditions added under section 7. This requirement modifies the requirement in section 4 to "keep intact all notices". c) You must license the entire work, as a whole, under this License to anyone who comes into possession of a copy. This License will therefore apply, along with any applicable section 7 additional terms, to the whole of the work, and all its parts, regardless of how they are packaged. This License gives no permission to license the work in any other way, but it does not invalidate such permission if you have separately received it. d) If the work has interactive user interfaces, each must display Appropriate Legal Notices; however, if the Program has interactive interfaces that do not display Appropriate Legal Notices, your work need not make them do so. A compilation of a covered work with other separate and independent works, which are not by their nature extensions of the covered work, and which are not combined with it such as to form a larger program, in or on a volume of a storage or distribution medium, is called an "aggregate" if the compilation and its resulting copyright are not used to limit the access or legal rights of the compilation's users beyond what the individual works permit. Inclusion of a covered work in an aggregate does not cause this License to apply to the other parts of the aggregate. 6. Conveying Non-Source Forms. You may convey a covered work in object code form under the terms of sections 4 and 5, provided that you also convey the machine-readable Corresponding Source under the terms of this License, in one of these ways: a) Convey the object code in, or embodied in, a physical product (including a physical distribution medium), accompanied by the Corresponding Source fixed on a durable physical medium customarily used for software interchange. b) Convey the object code in, or embodied in, a physical product (including a physical distribution medium), accompanied by a written offer, valid for at least three years and valid for as long as you offer spare parts or customer support for that product model, to give anyone who possesses the object code either (1) a copy of the Corresponding Source for all the software in the product that is covered by this License, on a durable physical medium customarily used for software interchange, for a price no more than your reasonable cost of physically performing this conveying of source, or (2) access to copy the Corresponding Source from a network server at no charge. c) Convey individual copies of the object code with a copy of the written offer to provide the Corresponding Source. This alternative is allowed only occasionally and noncommercially, and only if you received the object code with such an offer, in accord with subsection 6b. d) Convey the object code by offering access from a designated place (gratis or for a charge), and offer equivalent access to the Corresponding Source in the same way through the same place at no further charge. You need not require recipients to copy the Corresponding Source along with the object code. If the place to copy the object code is a network server, the Corresponding Source may be on a different server (operated by you or a third party) that supports equivalent copying facilities, provided you maintain clear directions next to the object code saying where to find the Corresponding Source. Regardless of what server hosts the Corresponding Source, you remain obligated to ensure that it is available for as long as needed to satisfy these requirements. e) Convey the object code using peer-to-peer transmission, provided you inform other peers where the object code and Corresponding Source of the work are being offered to the general public at no charge under subsection 6d. A separable portion of the object code, whose source code is excluded from the Corresponding Source as a System Library, need not be included in conveying the object code work. A "User Product" is either (1) a "consumer product", which means any tangible personal property which is normally used for personal, family, or household purposes, or (2) anything designed or sold for incorporation into a dwelling. In determining whether a product is a consumer product, doubtful cases shall be resolved in favor of coverage. For a particular product received by a particular user, "normally used" refers to a typical or common use of that class of product, regardless of the status of the particular user or of the way in which the particular user actually uses, or expects or is expected to use, the product. A product is a consumer product regardless of whether the product has substantial commercial, industrial or non-consumer uses, unless such uses represent the only significant mode of use of the product. "Installation Information" for a User Product means any methods, procedures, authorization keys, or other information required to install and execute modified versions of a covered work in that User Product from a modified version of its Corresponding Source. The information must suffice to ensure that the continued functioning of the modified object code is in no case prevented or interfered with solely because modification has been made. If you convey an object code work under this section in, or with, or specifically for use in, a User Product, and the conveying occurs as part of a transaction in which the right of possession and use of the User Product is transferred to the recipient in perpetuity or for a fixed term (regardless of how the transaction is characterized), the Corresponding Source conveyed under this section must be accompanied by the Installation Information. But this requirement does not apply if neither you nor any third party retains the ability to install modified object code on the User Product (for example, the work has been installed in ROM). The requirement to provide Installation Information does not include a requirement to continue to provide support service, warranty, or updates for a work that has been modified or installed by the recipient, or for the User Product in which it has been modified or installed. Access to a network may be denied when the modification itself materially and adversely affects the operation of the network or violates the rules and protocols for communication across the network. Corresponding Source conveyed, and Installation Information provided, in accord with this section must be in a format that is publicly documented (and with an implementation available to the public in source code form), and must require no special password or key for unpacking, reading or copying. 7. Additional Terms. "Additional permissions" are terms that supplement the terms of this License by making exceptions from one or more of its conditions. Additional permissions that are applicable to the entire Program shall be treated as though they were included in this License, to the extent that they are valid under applicable law. If additional permissions apply only to part of the Program, that part may be used separately under those permissions, but the entire Program remains governed by this License without regard to the additional permissions. When you convey a copy of a covered work, you may at your option remove any additional permissions from that copy, or from any part of it. (Additional permissions may be written to require their own removal in certain cases when you modify the work.) You may place additional permissions on material, added by you to a covered work, for which you have or can give appropriate copyright permission. Notwithstanding any other provision of this License, for material you add to a covered work, you may (if authorized by the copyright holders of that material) supplement the terms of this License with terms: a) Disclaiming warranty or limiting liability differently from the terms of sections 15 and 16 of this License; or b) Requiring preservation of specified reasonable legal notices or author attributions in that material or in the Appropriate Legal Notices displayed by works containing it; or c) Prohibiting misrepresentation of the origin of that material, or requiring that modified versions of such material be marked in reasonable ways as different from the original version; or d) Limiting the use for publicity purposes of names of licensors or authors of the material; or e) Declining to grant rights under trademark law for use of some trade names, trademarks, or service marks; or f) Requiring indemnification of licensors and authors of that material by anyone who conveys the material (or modified versions of it) with contractual assumptions of liability to the recipient, for any liability that these contractual assumptions directly impose on those licensors and authors. All other non-permissive additional terms are considered "further restrictions" within the meaning of section 10. If the Program as you received it, or any part of it, contains a notice stating that it is governed by this License along with a term that is a further restriction, you may remove that term. If a license document contains a further restriction but permits relicensing or conveying under this License, you may add to a covered work material governed by the terms of that license document, provided that the further restriction does not survive such relicensing or conveying. If you add terms to a covered work in accord with this section, you must place, in the relevant source files, a statement of the additional terms that apply to those files, or a notice indicating where to find the applicable terms. Additional terms, permissive or non-permissive, may be stated in the form of a separately written license, or stated as exceptions; the above requirements apply either way. 8. Termination. You may not propagate or modify a covered work except as expressly provided under this License. Any attempt otherwise to propagate or modify it is void, and will automatically terminate your rights under this License (including any patent licenses granted under the third paragraph of section 11). However, if you cease all violation of this License, then your license from a particular copyright holder is reinstated (a) provisionally, unless and until the copyright holder explicitly and finally terminates your license, and (b) permanently, if the copyright holder fails to notify you of the violation by some reasonable means prior to 60 days after the cessation. Moreover, your license from a particular copyright holder is reinstated permanently if the copyright holder notifies you of the violation by some reasonable means, this is the first time you have received notice of violation of this License (for any work) from that copyright holder, and you cure the violation prior to 30 days after your receipt of the notice. Termination of your rights under this section does not terminate the licenses of parties who have received copies or rights from you under this License. If your rights have been terminated and not permanently reinstated, you do not qualify to receive new licenses for the same material under section 10. 9. Acceptance Not Required for Having Copies. You are not required to accept this License in order to receive or run a copy of the Program. Ancillary propagation of a covered work occurring solely as a consequence of using peer-to-peer transmission to receive a copy likewise does not require acceptance. However, nothing other than this License grants you permission to propagate or modify any covered work. These actions infringe copyright if you do not accept this License. Therefore, by modifying or propagating a covered work, you indicate your acceptance of this License to do so. 10. Automatic Licensing of Downstream Recipients. Each time you convey a covered work, the recipient automatically receives a license from the original licensors, to run, modify and propagate that work, subject to this License. You are not responsible for enforcing compliance by third parties with this License. An "entity transaction" is a transaction transferring control of an organization, or substantially all assets of one, or subdividing an organization, or merging organizations. If propagation of a covered work results from an entity transaction, each party to that transaction who receives a copy of the work also receives whatever licenses to the work the party's predecessor in interest had or could give under the previous paragraph, plus a right to possession of the Corresponding Source of the work from the predecessor in interest, if the predecessor has it or can get it with reasonable efforts. You may not impose any further restrictions on the exercise of the rights granted or affirmed under this License. For example, you may not impose a license fee, royalty, or other charge for exercise of rights granted under this License, and you may not initiate litigation (including a cross-claim or counterclaim in a lawsuit) alleging that any patent claim is infringed by making, using, selling, offering for sale, or importing the Program or any portion of it. 11. Patents. A "contributor" is a copyright holder who authorizes use under this License of the Program or a work on which the Program is based. The work thus licensed is called the contributor's "contributor version". A contributor's "essential patent claims" are all patent claims owned or controlled by the contributor, whether already acquired or hereafter acquired, that would be infringed by some manner, permitted by this License, of making, using, or selling its contributor version, but do not include claims that would be infringed only as a consequence of further modification of the contributor version. For purposes of this definition, "control" includes the right to grant patent sublicenses in a manner consistent with the requirements of this License. Each contributor grants you a non-exclusive, worldwide, royalty-free patent license under the contributor's essential patent claims, to make, use, sell, offer for sale, import and otherwise run, modify and propagate the contents of its contributor version. In the following three paragraphs, a "patent license" is any express agreement or commitment, however denominated, not to enforce a patent (such as an express permission to practice a patent or covenant not to sue for patent infringement). To "grant" such a patent license to a party means to make such an agreement or commitment not to enforce a patent against the party. If you convey a covered work, knowingly relying on a patent license, and the Corresponding Source of the work is not available for anyone to copy, free of charge and under the terms of this License, through a publicly available network server or other readily accessible means, then you must either (1) cause the Corresponding Source to be so available, or (2) arrange to deprive yourself of the benefit of the patent license for this particular work, or (3) arrange, in a manner consistent with the requirements of this License, to extend the patent license to downstream recipients. "Knowingly relying" means you have actual knowledge that, but for the patent license, your conveying the covered work in a country, or your recipient's use of the covered work in a country, would infringe one or more identifiable patents in that country that you have reason to believe are valid. If, pursuant to or in connection with a single transaction or arrangement, you convey, or propagate by procuring conveyance of, a covered work, and grant a patent license to some of the parties receiving the covered work authorizing them to use, propagate, modify or convey a specific copy of the covered work, then the patent license you grant is automatically extended to all recipients of the covered work and works based on it. A patent license is "discriminatory" if it does not include within the scope of its coverage, prohibits the exercise of, or is conditioned on the non-exercise of one or more of the rights that are specifically granted under this License. You may not convey a covered work if you are a party to an arrangement with a third party that is in the business of distributing software, under which you make payment to the third party based on the extent of your activity of conveying the work, and under which the third party grants, to any of the parties who would receive the covered work from you, a discriminatory patent license (a) in connection with copies of the covered work conveyed by you (or copies made from those copies), or (b) primarily for and in connection with specific products or compilations that contain the covered work, unless you entered into that arrangement, or that patent license was granted, prior to 28 March 2007. Nothing in this License shall be construed as excluding or limiting any implied license or other defenses to infringement that may otherwise be available to you under applicable patent law. 12. No Surrender of Others' Freedom. If conditions are imposed on you (whether by court order, agreement or otherwise) that contradict the conditions of this License, they do not excuse you from the conditions of this License. If you cannot convey a covered work so as to satisfy simultaneously your obligations under this License and any other pertinent obligations, then as a consequence you may not convey it at all. For example, if you agree to terms that obligate you to collect a royalty for further conveying from those to whom you convey the Program, the only way you could satisfy both those terms and this License would be to refrain entirely from conveying the Program. 13. Use with the GNU Affero General Public License. Notwithstanding any other provision of this License, you have permission to link or combine any covered work with a work licensed under version 3 of the GNU Affero General Public License into a single combined work, and to convey the resulting work. The terms of this License will continue to apply to the part which is the covered work, but the special requirements of the GNU Affero General Public License, section 13, concerning interaction through a network will apply to the combination as such. 14. Revised Versions of this License. The Free Software Foundation may publish revised and/or new versions of the GNU General Public License from time to time. Such new versions will be similar in spirit to the present version, but may differ in detail to address new problems or concerns. Each version is given a distinguishing version number. If the Program specifies that a certain numbered version of the GNU General Public License "or any later version" applies to it, you have the option of following the terms and conditions either of that numbered version or of any later version published by the Free Software Foundation. If the Program does not specify a version number of the GNU General Public License, you may choose any version ever published by the Free Software Foundation. If the Program specifies that a proxy can decide which future versions of the GNU General Public License can be used, that proxy's public statement of acceptance of a version permanently authorizes you to choose that version for the Program. Later license versions may give you additional or different permissions. However, no additional obligations are imposed on any author or copyright holder as a result of your choosing to follow a later version. 15. Disclaimer of Warranty. THERE IS NO WARRANTY FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING, REPAIR OR CORRECTION. 16. Limitation of Liability. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MODIFIES AND/OR CONVEYS THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES. 17. Interpretation of Sections 15 and 16. If the disclaimer of warranty and limitation of liability provided above cannot be given local legal effect according to their terms, reviewing courts shall apply local law that most closely approximates an absolute waiver of all civil liability in connection with the Program, unless a warranty or assumption of liability accompanies a copy of the Program in return for a fee. END OF TERMS AND CONDITIONS How to Apply These Terms to Your New Programs If you develop a new program, and you want it to be of the greatest possible use to the public, the best way to achieve this is to make it free software which everyone can redistribute and change under these terms. To do so, attach the following notices to the program. It is safest to attach them to the start of each source file to most effectively state the exclusion of warranty; and each file should have at least the "copyright" line and a pointer to where the full notice is found. Copyright (C) This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program. If not, see . Also add information on how to contact you by electronic and paper mail. If the program does terminal interaction, make it output a short notice like this when it starts in an interactive mode: Copyright (C) This program comes with ABSOLUTELY NO WARRANTY; for details type `show w'. This is free software, and you are welcome to redistribute it under certain conditions; type `show c' for details. The hypothetical commands `show w' and `show c' should show the appropriate parts of the General Public License. Of course, your program's commands might be different; for a GUI interface, you would use an "about box". You should also get your employer (if you work as a programmer) or school, if any, to sign a "copyright disclaimer" for the program, if necessary. For more information on this, and how to apply and follow the GNU GPL, see . The GNU General Public License does not permit incorporating your program into proprietary programs. If your program is a subroutine library, you may consider it more useful to permit linking proprietary applications with the library. If this is what you want to do, use the GNU Lesser General Public License instead of this License. But first, please read . emms-6.00/Makefile0000664000175000017500000000605713746063641012260 0ustar yrkyrkGZIP=gzip MAN1PAGES=emms-print-metadata.1 DOCDIR=doc/ SRCDIR=src SITEFLAG=--no-site-file EMACS=emacs ALLSOURCE=$(wildcard *.el) SOURCE=$(filter-out $(SPECIAL),$(ALLSOURCE)) TARGET=$(patsubst %.el,%.elc,$(SOURCE)) ALLCOMPILED=$(wildcard *.elc) DESTDIR= PREFIX=$(DESTDIR)/usr/local INFODIR=$(PREFIX)/info MAN1DIR=$(PREFIX)/share/man/man1 BINDIR=$(PREFIX)/bin SITELISP=$(PREFIX)/share/emacs/site-lisp/emms GINSTALLINFO = /usr/bin/ginstall-info --info-dir=$(INFODIR) # For systems without ginstall-info INSTALLINFO = /usr/bin/install-info --info-dir=$(INFODIR) CHANGELOG_CMD = git log --pretty=medium --no-merges # The currently released version of EMMS VERSION=6.00 .PHONY: all install docs clean .PRECIOUS: %.elc all: emms-auto.el $(TARGET) docs emms-auto.el: emms-auto.in $(SOURCE) cp emms-auto.in emms-auto.el -rm -f emms-auto.elc @$(EMACS) -q $(SITEFLAG) -batch \ -l emms-maint.el \ -l emms-auto.el \ -f emms-generate-autoloads \ $(shell pwd)/emms-auto.el . %.elc: %.el @$(EMACS) -q $(SITEFLAG) -batch \ -l emms-maint.el \ -f batch-byte-compile $< docs: $(MAKE) -C $(DOCDIR) for file in $(DOCDIR)*.info; do install-info $$file dir; done cp $(DOCDIR)emms.info $(CURDIR)/ emms-print-metadata: $(SRCDIR)/emms-print-metadata.cpp $(CXX) $(CPPFLAGS) $(CXXFLAGS) $(LDFLAGS) -o $(SRCDIR)/$@ $< `taglib-config --cflags --libs` install: test -d $(SITELISP) || mkdir -p $(SITELISP) test -d $(INFODIR) || install -d $(INFODIR) install -m 644 $(ALLSOURCE) $(SITELISP) install -m 644 $(ALLCOMPILED) $(SITELISP) install -m 0644 $(DOCDIR)emms.info $(INFODIR)/emms.info for p in $(MAN1PAGES) ; do $(GZIP) -9c $$p > $(MAN1DIR)/$$p.gz ; done if [ -x /usr/bin/ginstall-info ]; then \ $(GINSTALLINFO) $(DOCDIR)emms.info; \ else \ $(INSTALLINFO) $(DOCDIR)emms.info; \ fi if [ -x $(SRCDIR)/emms-print-metadata ]; then \ echo "emms-print-metadata found, installing"; \ install -m 755 $(SRCDIR)/emms-print-metadata $(BINDIR)/emms-print-metadata; \ else \ echo "skipping emms-print-metadata install"; \ fi remove-info: if [ -x /usr/bin/ginstall-info ]; then \ $(GINSTALLINFO) --remove $(DOCDIR)emms.info; \ else \ $(INSTALLINFO) --remove $(DOCDIR)emms.info; \ fi ChangeLog: $(CHANGELOG_CMD) > $@ clean: -rm -f *~ $(DOCDIR)emms.info $(DOCDIR)emms.html $(SRCDIR)/emms-print-metadata -rm -f *~ *.elc emms-auto.el -rm -f emms.info dist: clean emms-auto.el git archive --format=tar --prefix=emms-$(VERSION)/ HEAD | \ (cd .. && tar xf -) rm -f ../emms-$(VERSION)/.gitignore cp emms-auto.el ../emms-$(VERSION) $(CHANGELOG_CMD) > ../emms-$(VERSION)/ChangeLog release: dist (cd .. && tar -czf emms-$(VERSION).tar.gz \ emms-$(VERSION) ; \ gpg --detach emms-$(VERSION).tar.gz) upload: (cd .. && echo "version: 1.2\ndirectory: emms\nfilename: "emms-$(VERSION).tar.gz"\ncomment: new version of Emms" | gpg --clearsign > emms-$(VERSION).tar.gz.directive.asc && echo open ftp://ftp-upload.gnu.org > upload.lftp ; echo cd /incoming/ftp >> upload.lftp ; echo mput emms-$(VERSION).tar.gz* >> upload.lftp ; echo close >> upload.lftp ; lftp -f upload.lftp ; rm -f upload.lftp) emms-6.00/NEWS0000664000175000017500000001745213746063641011320 0ustar yrkyrkNews since version 5.4 - Emms is now available via the GNU ELPA repository. - New info method: tinytag. - New info method: exiftool. - emms-volume.el: Fix missing quote in emms-volume-change-function. - namespace cleanup (emms-later-do.el). News since version 5.3 - Updated Website launched. - New and simplified emms-streams.el implementation. - New streaming radio stations. - Use track-at-point as a hint for guessing emms-add directory. - Bug fix: prevent skipping track when switching them during mpv playback. - Mixerctl now availabe in custom interface. News since version 5.2 - emms-volume-mixerctl.el: mixerctl volume control. - emms-playlist-save: improve behavior. - emms-playing-time: add a count-down timer display style. - Try to auto-detect the appropriate volume control. News since version 5.1 - emms-browser.el: faster thumbnail cache lookups. - emms-player-mpd.el: Parse disc number for mpd tracks. - Make thing-at-point behavior more consistent. - Remove redundant functions in code. - Allow changing the mode-line icon. - Bug fix: emms-player-mode, more consistent behavior. - Bug fix: emms-browser, Don't rely on (interactive "r"). News since version 5.0 - Add `emms-toggle-single-track'. - Fix the way emms-score skips tracks. - Safer key-binding for interactively killing the playlist buffer. - Bug fix: emms-show-all quit now behaves well. - Bug fix: Metalplaylist focus would error without a current buffer. - emms-playlist-sort sorts the visible playlist. - Rewrite emms-playlist-limit implementation. Now operates on the current buffer rather than the current playlist. Add emms-playlist-limit-to-description. - Rewrite mpv backend to use long-running mpv instances controlled over json-rpc protocol for newer versions. 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 - Bug fix: set-playlist-buffer listing. - emms-source-file-directory-tree-find now follows symlinks. - Playlists can now be sorted by mtime. - Move to cl-lib. - Improve emms-volume. - Bug fix: fix mpg321 autoplay. News since version 4.2: - Limit network lookups in Browser mode. - New (C++) emms-print-metadata brings more TagLib features. - Compilation warnings gone (excl. cl). - Bug fix: emms-lyrics free variable fix. News since version 4.1: - Removed defunct streams. - Various emms-tag-editor bug fixes. - Bug fix: Info file now installs with correct suffix. - Bug fix: `make install' now installs emms-print-metadata. News since version 4.0: - Change the default behavior of C-k in emms-playlist-mode. - Covers can have several extensions. See `emms-browser-covers-file-extensions'. - Libre.fm login details can, and should, be stored in authinfo now. - Possible to set volume via PulseAudio pactl via emms-volume-pulse.el. - emms-lyrics.el now uses eww if present. Also EMMS tries to fetch non-Chinese lyrics from lyricwiki.org. - Add HTTPS support where possible. - Sort using locale language in the browser, if possible. - emms-setup.el has been simplified. - The Emms manual has been revised to help new users. - New feature: M-x emms-show-all. News since version 3.0: - Add GNU FM support. - Added mp4, m4a to the extensions handled by emms-info-libtag. - Play tracks randomly. - Extend MPD player support. - Add pause-resume support for lyrics display. - New implementation of emms-print-metadata. - Support both XEmacs and Emacs to highlight playing lyrics. - Add support for disc-number sorting of FLAC files. - New function to allow custom browser track-formats to display track duration. - Drop support for emms-player-gstreamer, Last.fm. - emms-player-mplayer: Remove code for loading movie subtitles automatically by emms, since mplayer has an option (`sub-fuzziness') controlling that. - Support displaying lyrics in a dedicated buffer, to highlight playing lyric. - Fix make install on Cygwin. - Compilation errors cleanup. News since version 2.1: - Saving bookmarks in individual tracks is now supported. - Support deleting files from the cache. - Add mms:// URL support for emms-player-mplayer. - Implement pause, resume, and seek support for emms-player-alsaplayer. - A new player called emms-player-timidity has been implemented which is capable of playing midi files. - A new player called emms-player-fluidsynth is also capable of playing midi files. - A new player called emms-player-xine (in emms-player-xine.el) is capable of using Xine to play tracks. - Hitting "<" or ">" in emms-playlist-mode causes seeking backward and forward, respectively. - New file jack.el allows jackd to be started from within emacs, and permits clients to be connected or disconnected. - New file emms-tag-editor.el is capable of editing track information in songs. - New file emms-mark.el allows tracks in a playlist to be marked and operated on, much like dired mode. - New file emms-lastfm.el implements submitting track information to Last.fm and playing Last.fm radio streams. Support for playing these streams has been added to emms-streams.el. - New file emms-i18n.el adds support for handling coding systems properly in process input/output. This is currently only used by emms-info-mp3info.el. - New file emms-history.el causes playlists to be saved automatically when exiting Emacs. - emms-player-mpd: - Using the emms-browser to insert and play tracks now works properly with emms-player-mpd. - Display the correct error message if an error occurs while trying to play a stream. - Handle any encoding errors that occur during playback. - Integrate with emms-lastfm.el in `emms-player-mpd-show', if emms-lastfm is loaded and active. - emms-playing-time supports different display styles now. - emms-lyrics: Now support lyrics auto-scrolling. - emms-player-mplayer: Capable of loading movie subtitles automatically now. News since version 2.0: - A new player that uses mpg321's remote mode is now available (emms-player-mpg321-remote)--this allows seeking and copes with errors in files. - A metadata browser has been added in emms-browser.el. - Recording of the time a track was last played is now supported. - emms-play-* and emms-add-* functions now toggle their play/add behavior when a prefix argument is supplied. - EMMS now caches tracks, which speeds up loading of large collections with info tags considerably. - EMMS now knows how to change the volume (emms-volume.el). - When playing a playlist from emms-playlist-mode, EMMS now optionally opens a new buffer for this playlist. User-visible bug fixes: - The emms-playlist-mode is now much faster. - MP3s with errors are now playable when using the remote player. emms-6.00/README0000664000175000017500000000020713746063641011467 0ustar yrkyrkPlease read the fine manual which is available in the doc directory. We do our best to make sure that it's up to date and informative. emms-6.00/THANKGNU0000664000175000017500000000121613746063641011752 0ustar yrkyrkThis file lists some of the many people who submitted small but helpful changes to Emms. The contributions are too small to require copyright assignment and addition to the AUTHORS file (but are nevertheless much appreciated.) Alfred M. Szmidt Alexis Christian Faulhammer Dieter Deyke Dirk-Jan C. Binnema Ian D Jesse Weinstein Katherine Whitlock Luca Capello Mandar Mitra Sascha Wilde Tom Rauchenwald fledermaus at #emacs indio on #emacs emms-6.00/dir0000664000175000017500000000114013746063641011305 0ustar yrkyrkThis is the file .../info/dir, which contains the topmost node of the Info hierarchy, called (dir)Top. The first time you invoke Info you start off looking at this node.  File: dir, Node: Top This is the top of the INFO tree This (the Directory node) gives a menu of major topics. Typing "q" exits, "?" lists all Info commands, "d" returns here, "h" gives a primer for first-timers, "mEmacs" visits the Emacs manual, etc. In Emacs, you can click mouse button 2 on a menu item or cross reference to select it. * Menu: Emacs * Emms: (emms). The Emacs Multimedia System emms-6.00/doc/0000775000175000017500000000000013746063641011355 5ustar yrkyrkemms-6.00/doc/Makefile0000664000175000017500000000030213746063641013010 0ustar yrkyrk# Don't delete if make is interrupted .PRECIOUS: %.info %.html all: emms.info clean: rm -f *.info %.info: %.texinfo makeinfo --no-split $< %.html: %.texinfo makeinfo --html --no-split $< emms-6.00/doc/developer-release.txt0000664000175000017500000000140313746063641015517 0ustar yrkyrkThis is an explanation of how to make a release for Emms. Emms is currently distributed in three different ways: via the Git repo on Savannah, as a tarball from GNU, and via GNU ELPA. * Increase the version number in emms.el (variable, elpa header), 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"' * Run make release * Run make upload * Update copy of emms.info in root directory * Update online manual * Update website * Push to GNU ELPA: push to the Savannah "elpa" branch, and from there "git push elpa elpa:refs/heads/externals/emms" * Send announcement email to gnu-info and to the emms mailing list emms-6.00/doc/emms.texinfo0000664000175000017500000024112113746063641013715 0ustar yrkyrk\input texinfo @c -*-texinfo-*- @c %**start of header @setfilename emms.info @settitle The Emms Manual @c %**end of header @c History: The Emms manual was almost entirely rewritten for the @c release of Emms version 2. @dircategory Emacs @direntry * Emms: (emms). The Emacs Multimedia System @end direntry @copying @copyright{} 2004, 2005, 2006, 2007, 2008, 2009, 2010, 2011, 2014, 2015, 2016, 2020 Free Software Foundation, Inc. @quotation Permission is granted to copy, distribute and/or modify this document under the terms of the GNU Free Documentation License, Version 1.1 or any later version published by the Free Software Foundation; with no Invariant Sections, no Front-Cover Texts, and no Back-Cover Texts. A copy of the license is included in the section entitled "GNU Free Documentation License". @end quotation @end copying @c For printed material @titlepage @title The Emms Manual @page @vskip 0pt plus 1filll @insertcopying @end titlepage @contents @c END For printed material @ifnottex @node Top, Introduction, (dir), (dir) @top Emms Manual This is the Manual for the Emacs Multimedia System. @insertcopying @menu Starting out * Introduction:: Introduction to Emms. * Quickstart Guide:: First steps with Emms for new users. * Installation:: How to install Emms on your System. * Setup:: How to setup Emms. * Configuration:: More detailed setup and configuration. * Getting Help:: Where to get help with Emms and make suggestions. * Formats and Freedom:: File formats without restrictions. Emms basics * Basic Commands:: How to control Emms with ease. * The Core File:: The inner core of Emms. * Sources:: Sources for playlists-creation. * Simple Players:: Some simple players. * Playlists:: How Emms organizes media. Advanced Features * Track Information:: More narrative track descriptions. * Interactive Playlists:: Interactive Playlists. * Markable Playlists:: Allow tracks to be marked. * Extending Emms:: How to define new players and modules. Modules and Extensions * The Browser:: Advanced metadata browsing. * Sorting Playlists:: Sorting the order of the tracks. * Persistent Playlists:: Restoring playlists on emacs startup. * Editing Tracks:: Editing track information from within Emms. * Emms Mode Line:: Emms information on the mode line. * Limiting:: Derive a new playlist from the current. * Music Player Daemon:: Interface to Music Player Daemon. * Lyrics:: Displaying lyrics synchronously. * Volume:: Changing the volume. * 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 * Copying:: The GNU General Public License gives you permission to redistribute Emms on certain terms; it also explains that there is no warranty. * The GNU FDL:: The license for this documentation. Indices * Concept Index:: * Function Index:: * Variable Index:: * Keybinding Index:: @detailmenu --- The Detailed Node Listing --- Here are some other nodes which are really inferiors of the ones already listed, mentioned here so you can get to them in one step: Installation * Compiling Emms:: Compiling Emms into Byte-Code. The Core File * User Variables:: Variables for the user to tweak. * Hooks:: Hooks for important Emms functions. * Core Functions:: Providing the basic functionality of Emms. Track Information * Using tinytag:: Track information via tinytag. * Using exiftool:: Track information via exiftool. * Using TagLib:: TagLib for track information. * Defining Info Methods:: Defining new info methods. Extending Emms * New Player:: How to define a new player. * Simple Player for `play':: Example player using @command{play}. * More Complex Player:: Example of a complex player using @command{mpg321}. @end detailmenu @end menu @end ifnottex @c ------------------------------------------------------------------- @node Introduction @chapter Introduction @cindex introduction Emms is the Emacs Multi-Media System. Emms organizes playlists, allows browsing through track and album metadata, and plays files by calling external players. This manual tries to be the definitive source of information about Emms, an online version of the manual is available at: @uref{http://www.gnu.org/software/emms/manual/}. The basic functionality of Emms consists of three parts: The core, the sources, and the players. The core resides in @file{emms.el}, and provides a simple playlist and the basic functionality to use all the other features of Emms. It provides the common user commands and interfaces for other parts. It thinks in tracks, where a track is the combination of a type and a name - e.g. the track type 'file has a name that is the file name. Other track types are possible. To get to tracks, the core needs sources. The file @file{emms-source-file.el} provides simple sources to interact with the file system. When Emms finally has the sources in the playlist, it needs a player to play them. @file{emms-player-simple.el} defines a few useful players, and allows you to define your own in a very simple way. The Emms core comes with many additional features to extend its functionality. The way Emms works is easy to customize with your own code or by using `M-x customize' or by changing the variables directly. @c ------------------------------------------------------------------- @node Quickstart Guide @chapter Quickstart Guide This chapter demonstrates how to setup Emms so that you can start listening to your music without having to read all of the documentation first. This is the tl;dr version of the manual. The first thing you have to do is telling Emacs where Emms is located. Let's say you have it in @file{~/elisp/emms/}. So add this line to your @file{.emacs}: @lisp (add-to-list 'load-path "~/elisp/emms/lisp/") @end lisp More detailed information about installing Emms can be found in the installation chapter, @xref{Installation}. You'll then want to load Emms into Emacs. To achieve this you invoke the @code{emms-all} setup function by adding the following three lines to your @file{.emacs}. @lisp (require 'emms-setup) (emms-all) (emms-default-players) @end lisp 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, 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 a number of pieces of software and libraries as sources for track info, see @xref{Track Information} for more. 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 @file{~/Music} or in subdirectories thereof. @lisp (setq emms-source-file-default-directory "~/Music/") @end lisp OK, now we've set up Emms. Reload your @file{.emacs} or restart Emacs to let the changes have an effect. Now we will add all our music to a playlist by invoking @kbd{M-x emms-add-directory-tree RET ~/Music/ RET}. We do this because then Emms will read the tags of all your music files and caches them (this is also required for the Emms browser, @xref{The Browser}.) To switch to the playlist buffer, invoke @kbd{M-x emms-playlist-mode-go} or simply @kbd{M-x emms}. You may see that some tracks are displayed with their file name, but as Emms populates its tag cache, track by track, the filenames get replaced with the artist and track name of the file's tag. Go ahead and navigate to a track and hit @kbd{RET} on it to start playback. Now you can start exploring Emms. It's probably best to begin with the basic commands (@pxref{Basic Commands}), the interactive playlists (@pxref{Interactive Playlists}), and the browser (@pxref{The Browser}). @c ------------------------------------------------------------------- @node Installation @chapter Installation @cindex installation Emms is available via GNU ELPA, which takes care of all of the following steps automatically. If you are installing Emms manually, you need to put all the .el files of emms in a directory in your load-path. For example, if you put all those files into ~/elisp/emms/, then in your ~/.emacs, you should add: @lisp (add-to-list 'load-path "~/elisp/emms/lisp/") @end lisp @noindent @menu * Compiling Emms:: Compiling Emms into Byte-Code. @end menu @node Compiling Emms @section Compiling Emms @cindex compiling If you are using XEmacs, you will need to edit @file{Makefile} as follows before continuing. @example EMACS=xemacs SITEFLAG=-no-site-file @end example You can byte-compile Emms by first entering the directory containing the Emms source code, followed by invoking: @command{make} Which will byte compile Emms. You can then invoke: @command{make install} Which will install Emms into your Emacs directories (provided you have the appropriate permissions to do so on your system). Note that Emms is a light-weight and agile program, you can therefore run Emms just fine without byte compiling it. @c ------------------------------------------------------------------- @node Setup @chapter Setup @cindex setup @cindex setting up Emms @cindex quick setup The `emms-setup' feature is provided by the file @file{emms-setup.el}. It is essentially a collection of shortcuts for loading different Emms features quickly, but everything you can do with `emms-setup' can also be done manually. We use `emms-setup' by calling one of the setup functions. @defun emms-minimalistic An Emms setup script. Playlists and all the basics for playing media, but nothing else. @end defun @defun emms-all An Emms setup script. Loads all the stable features which come with the Emms distribution. @end defun `emms-setup' also comes with a convenience function to set a default list of media players. @defun emms-default-players Set @var{emms-player-list} to @var{emms-setup-default-player-list}. @end defun You can of course write your own Emms setup functions like the above by looking at the existing function definitions in @file{emms-setup.el}. @c ------------------------------------------------------------------- @node Configuration @chapter Configuration @cindex Configuration This chapter discusses the configuration of Emms in more detail. The following code fragment provides a minimal Emms setup without using the layer of `emms-setup'. It can maybe be used to better understand the internals of Emms. You can see how Emms needs to know about players (these are defined in `emms-player-simple') and about sources for tracks (trivial file system based sources, such as this `emms-directory-tree', are defined in `emms-source-file'). @lisp (require 'emms-player-simple) (require 'emms-source-file) (require 'emms-source-playlist) (setq emms-player-list '(emms-player-mpg321 emms-player-ogg123 emms-player-mplayer)) @end lisp For a discussion on how to define additional players, see @xref{Simple Players}. Much of the behaviour of Emms can be changed by setting variables. For example: @lisp (setq emms-info-asynchronously nil) (setq emms-playlist-buffer-name "*Music*") @end lisp The first @code{setq} turns off the asynchronous updating of info tags. The second sets the default name of the Emms playlist buffer. Another way to change Emms variables is to use the M-x @command{customize} mechanism provided by Emacs. @menu * Finding files and speed:: Finding files quickly or portably. @end menu @node Finding files and speed @section Finding files and speed @cindex files @cindex speed Emms needs to traverse directories in order to find playable media. The default method Emms uses to achive this is @code{emms-source-file-directory-tree-internal} as defined in @file{emms-source-file.el}. The above method is written portably and will always work, but might be too slow if we want to load several hundred tracks (or more). @file{emms-source-file.el} defines another method for finding files, @code{emms-source-file-directory-tree-find} which uses GNU/find. @code{emms-source-file-directory-tree-find} is usually an order of magnitude faster, but of course will not work if you do not have GNU/find installed. The method Emms will use is defined in the customisable variable @var{emms-source-file-directory-tree-function}. @c ------------------------------------------------------------------- @node Getting Help @chapter Getting Help @cindex mailing list @cindex website If you have a bug to report, need help, or wish to suggest a feature, please feel free to use the Emms mailing list. The address of the list is emms-help@@gnu.org. To subscribe to it, visit @url{http://lists.gnu.org/mailman/listinfo/emms-help}. If you are familiar with the Gmane service, there is a Gmane newsgroup which mirrors this mailing address at gmane.emacs.emms.user. Emms also has a website at @url{http://www.gnu.org/software/emms/}. @c ------------------------------------------------------------------- @node Formats and Freedom @chapter Formats and Freedom @cindex freedom @cindex format Emms is free software, but some of the file formats it can play carry restrictions, they are proprietary file formats. Proprietary software companies are pushing out audio and video formats which restrict when, where and how you can play them, and restrict developers from writing free software which interacts with them. Restrictive file formats put the corporate bottom-line before the public interest. Fortunately there are alternatives like Ogg. Ogg is a professional grade multimedia format. Ogg Vorbis is the compressed audio format (like MP3), and Ogg Theora is the video format. For more information, go to @url{http://www.xiph.org/}. If you want to transcode audio into a lossless format, you can try FLAC (Free Lossless Audio Codec). FLAC stands out as the fastest and most widely supported lossless audio codec, and the only one that at once is non-proprietary, is unencumbered by patents and has the source code for a reference implementation freely available. For more information about FLAC, go to @url{http://flac.sourceforge.net/}. @c ------------------------------------------------------------------- @node Basic Commands @chapter Basic Commands @cindex basic commands @cindex commands, basic Before you can use the interface commands, you need a playlist to start with. The following commands allow you to add to the current playlist from different sources: Note that the commands with the ``emms-add-'' prefix add the source to the playlist but do not start playing it immediately. Conversely, the commands with the ``emms-play-'' prefix begin playing the track immediately. @defun emms-play-file file A source for a single file - either @var{file}, or queried from the user. If called with a prefix the file will be added like @command{emms-add-file}. @end defun @defun emms-add-file file A source for a single file - either @var{file}, or queried from the user. If called with a prefix the file will be played like @command{emms-play-file}. @end defun @defun emms-play-directory dir A source for a whole directory tree - either @var{dir}, or queried from the user. @end defun @defun emms-add-directory dir A source for a whole directory tree - either @var{dir}, or queried from the user. @end defun @defun emms-play-directory-tree dir A source for multiple directory trees - either @var{dir}, or the value of @var{emms-source-file-default-directory}. @end defun @defun emms-add-directory-tree dir A source for multiple directory trees - either @var{dir}, or the value of @var{emms-source-file-default-directory}. @end defun @defun emms-play-url url A source for an @var{url} - for example, for streaming. @end defun @defun emms-add-url url A source for an @var{url} - for example, for streaming. @end defun @defun emms-play-playlist playlist A source for the M3u or PLS playlist format from the file @var{playlist}. @end defun @defun emms-add-playlist playlist A source for the M3u or PLS playlist format from the file @var{playlist}. @end defun @defun emms-play-find dir regexp A source that will find files in @var{dir} or @var{emms-source-file-default-directory} which match @var{regexp}. @end defun @defun emms-add-find dir regexp A source that will find files in @var{dir} or @var{emms-source-file-default-directory} which match @var{regexp}. @end defun The basic functionality of Emms is just to play music without being noticed. It provides a few commands to skip the current track and such, but other than that it doesn't show up. Emms provides the following basic user commands (which you might want to bind to keystrokes): @defun emms-start Start playing the current playlist @end defun @defun emms-stop Stop playing @end defun @defun emms-next Start playing the next track in the playlist @end defun @defun emms-previous Start playing previous track in the playlist @end defun @defun emms-shuffle Shuffle the current playlist. This uses @var{emms-playlist-shuffle-function}. @end defun @defun emms-sort Sort the current playlist. This uses @var{emms-playlist-sort-function}. @end defun @defun emms-show &optional insertp Describe the current Emms track in the minibuffer. If @var{insertp} is non-nil, insert the description into the current buffer instead. This function uses @var{emms-show-format} to format the current track. @end defun The command @command{emms-show-all} will pop up a window with the complete information about the track being played. @command{emms-show-all} is provided by @file{emms-show-all.el}, which is included in the `emms-all' setup level. See @xref{Setup}. @c ------------------------------------------------------------------- @node The Core File @chapter The Core File @cindex core file @cindex heart of Emms @cindex primitive functions The core file @file{emms.el} provides the all basic functions for playing music, generating playlists and defining players. @menu * User Variables:: Variables for the user to tweak. * Hooks:: Hooks for important Emms functions. * Core Functions:: Providing the basic functionality of Emms. @end menu @node User Variables @section User Variables @cindex user variables @cindex options The core file defines a number of user variables. @defopt emms-player-list A list of players Emms can use. You need to set this in order to use Emms to play media. @end defopt @defopt emms-show-format The format to use for @command{emms-show}. Any "%s" is replaced by what @var{emms-track-description-function} returns for the currently playing track. @end defopt @defopt emms-repeat-playlist Non-nil if the Emms playlist should automatically repeat the playlist. If nil, playback will stop when the last track finishes playing. @end defopt @defopt emms-track-description-function Function for describing an Emms track in a user-friendly way. @end defopt @defopt emms-sort-lessp-function A function that compares two tracks, and returns non-nil if the first track should be sorted before the second (see also @code{sort}). @end defopt @node Hooks @section Hooks @cindex hooks @cindex adding functionality The core file provides hook variables for the basic functionality of Emms. @defopt emms-player-started-hook A hook run when an Emms player started playing. @end defopt @defopt emms-player-stopped-hook A hook run when an Emms player stopped playing. See also @var{emms-player-finished-hook}. @end defopt @defopt emms-playlist-source-inserted-hook Hook run when a source got inserted into the playlist. The buffer is narrowed to the new tracks. @end defopt @defopt emms-playlist-selection-changed-hook Hook run after another track is selected in the Emms playlist. @end defopt @defopt emms-playlist-cleared-hook Hook run after the current Emms playlist is cleared. This happens both when the playlist is cleared and when a new buffer is created for it. @end defopt @defopt emms-player-finished-hook Hook run when an Emms player finishes playing a track. Please pay attention to the differences between @var{emms-player-finished-hook} and @var{emms-player-stopped-hook}. The former is called only when the player is stopped interactively; the latter, only when the player actually finishes playing a track. @end defopt @defopt emms-player-paused-hook Hook run when a player is paused or resumed. Use @var{emms-player-paused-p} to find the current state. @end defopt @node Core Functions @section Core Functions @cindex core functions @cindex basic functions The core file also defines all the functions important to the basic use of Emms. There are functions which deal with movement in the playlist. @defun emms-next-noerror Start playing the next track in the Emms playlist. Unlike @code{emms-next}, this function doesn't signal an error when called at the end of the playlist. This function should only be called when no player is playing. This is a good function to put in @code{emms-player-finished-hook}. @end defun @defun emms-playlist-next Move to the previous track in the current buffer. @end defun @defun emms-playlist-previous Move to the previous track in the current buffer. @end defun @defun emms-random Jump to a random track. @end defun @defun emms-toggle-repeat-playlist Toggle whether emms repeats the playlist after it is done. See @var{emms-repeat-playlist}. @end defun @defun emms-toggle-repeat-track Toggle whether emms repeats the current track. See @var{emms-repeat-track}. @end defun @defun emms-toggle-random-playlist Toggle whether emms plays the tracks randomly or sequentially. See @end defun @var{emms-random-playlist}. Some functions deal with the getting and setting track information. @defun emms-track type name Create a track with type @var{type} and name @var{name}. @end defun @defun emms-track-type track Return the type of @var{track}. @end defun @defun emms-track-name track Return the name of @var{track}. @end defun @defun emms-track-get name track &optional inexistent Return the value of @var{name} for @var{track}. If there is no value, return @var{default} (or nil, if not given). @end defun @defun emms-track-set track name value Set the value of @var{name} for @var{track} to @var{value}. @end defun @defun emms-track-description track Return a description of @var{track}. This function uses @var{emms-track-description-function}. @end defun @defun emms-player-for track Return an Emms player capable of playing @var{track}. This will be the first player whose PLAYABLEP function returns non-nil, or nil if no such player exists. @end defun @defun emms-playlist-current-selected-track Return the currently selected track in the current playlist. @end defun There are also functions which deal with the playing itself. @defun emms-player-start track Start playing @var{track}. @end defun @defun emms-player-stop Stop the currently playing player. @end defun @defun emms-player-stopped Declare that the current Emms player is finished. This should only be done by the current player itself. @end defun @defun emms-seek seconds Seek the current player @var{seconds} seconds. This can be a floating point number for sub-second fractions. It can also be negative to seek backwards. @end defun @defun emms-seek-forward Seek ten seconds forward. @end defun @defun emms-seek-backward Seek ten seconds backward. @end defun For more basic commands defined in the core file see @xref{Basic Commands}. @c ------------------------------------------------------------------- @node Sources @chapter Sources @cindex Sources Sources allow Emms to add and play tracks. Emms comes with a number of sources of its own. Sources are designed so that creating new ones will be easy. For examples of Emms sources for files and directories see @file{emms-source-file.el}. @defopt emms-source-file-default-directory The default directory to look for media files. @end defopt @defun emms-play-find Play all files in @var{emms-source-file-default-directory} that match a specific regular expression. @end defun @defun emms-source-file &optional file An Emms source for a single file - either @var{file}, or queried from the user. @end defun @defun emms-source-files files An Emms source for a list of @var{files}. @end defun @defun emms-source-directory &optional dir An Emms source for a whole directory tree - either @var{dir}, or queried from the user @end defun @defun emms-source-directory-tree & optional dir An Emms source for multiple directory trees - either @var{dir}, or the value of @var{emms-source-file-default-directory}. @end defun @defun emms-source-playlist file An Emms source for playlists. See @var{emms-source-playlist-formats} for a list of supported formats. @end defun @defun emms-source-playlist-native file An Emms source for a native Emms playlist file. @end defun @defun emms-source-playlist-m3u file An Emms source for an m3u playlist file. @end defun @defun emms-source-playlist-pls file An Emms source for a pls playlist file. @end defun @defun emms-source-find &optional dir regex An Emms source that will find files in @var{dir} or @var{emms-source-file-default-directory} that match @var{regexp}. @end defun @defun emms-source-file-directory-tree &optional dir Return a list of all files under @var{dir} which match @var{regex}. @end defun @defun emms-source-dired Play all marked files of a dired buffer @end defun @defun emms-source-file-regex Return a regexp that matches everything any player (that supports files) can play. @end defun @defun emms-locate regexp Search for @var{regexp} and display the results in a locate buffer @end defun @c ------------------------------------------------------------------- @node Simple Players @chapter Simple Players @cindex players, simple @defmac define-emms-simple-player name types regex command &rest args Define a simple player. @var{name} is used to construct the name of the function like emms-player-@var{name}. @var{types} is a list of track types understood by this player. @var{regex} must be a regexp that matches the filenames the player can play. @var{command} specifies the command line argument to call the player and @var{args} are the command line arguments. @end defmac For a discussion on how to define new players see @xref{New Player}. @defun emms-player-simple-stop Stop the currently playing process, if indeed there is one. @end defun @defun emms-player-simple-start filename cmdname params Starts a process playing @var{filename} using the specified @var{cmdname} with the specified @var{params}. @end defun @defun emms-player-simple-sentinel proc str Sentinel for determining the end of process for the process @var{proc} and the sentinel string @var{str}. @end defun @c ------------------------------------------------------------------- @node Playlists @chapter Playlists @cindex organizing tracks and media Emms uses Emacs buffers to store the media tracks for playing. We call one such buffer a ``playlist buffer'' or an ``Emms playlist buffer''. Emms then proceeds to play the media tracks in the buffer from top to bottom until the end of the playlist. The name of the playlist buffer is defined in the variable @var{emms-playlist-buffer-name} and is set to be an invisible Emacs buffer by default. You can change to any name you want. For an example configuration see @xref{Configuration}. You can create any number of playlist buffers you wish. At any time Emms has a single ``current'' buffer through which it proceeds track by track. @defun emms-playlist-new &optional name Create a new playlist buffer. The buffer is named @var{name}, but made unique. @var{name} defaults to `emms-playlist-buffer-name'. If called interactively, the new buffer is also selected. @end defun @defun emms-playlist-save &optional format file Store the current playlist to FILE as the type FORMAT. The default format is specified by @var{emms-source-playlist-default-format}. @end defun The current Emms playlist buffer is stored in the variable @var{emms-playlist-buffer}. @c ------------------------------------------------------------------- @node Track Information @chapter Track Information @cindex track information @cindex info tags Without a way to read the embedded track information inside files, Emms will only be able to list file names and file locations. Therefore Emms is distributed with support for a number of pieces of software and libraries which can be used to provide access to track metadata such as the artist's name, track name, album title, etc. Emms can use a number of different ways to populate the playlist with track information. These methods require the installation some additional software, free software of course, that Emms can then call to read the metadata from the files. @itemize @bullet @item Tinytag, a small python utility. See @xref{Using tinytag}. @item Exiftool, written in perl. See @xref{Using exiftool}. @item The TagLib library can be used by compiling a small piece of ``shim'' software. See @xref{Using TagLib}. @end itemize You can also use a combination of format-specific tools if needed, such as @file{emms-info-mp3info.el}, @file{emms-info-ogginfo.el}, @file{emms-info-opusinfo.el}, and @file{emms-cue.el}. These 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. Automatic track information retrieval is enabled by default in the `emms-all' setup level provided by @file{emms-setup.el}. For more information about @file{emms-setup.el} see @xref{Setup}. If you would like to know how Emms track retreival works and how we can define new methods for track retrieval see @xref{Defining Info Methods}. There are a number of user variables which control the behaviour of `emms-info'. @defopt emms-info-auto-update Non-nil when Emms should update track information if the file changes. This will cause hard drive activity on track loading. If this is too annoying for you, set this variable to nil. @end defopt @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 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 track as argument. @end defopt @menu * Using tinytag:: Track information via tinytag. * Using exiftool:: Track information via exiftool. * Using TagLib:: TagLib for track information. * Defining Info Methods:: Defining new info methods. @end menu @node Using tinytag @section Using tinytag @cindex Using tinytag Make sure that the python program tinytag is installed on your system. It is available at @uref{https://pypi.org/project/tinytag/, tinytag}. Configure tinytag as the sole info method (competing and overlapping methods can cause confusion) for Emms: @lisp (setq emms-info-functions '(emms-info-tinytag)) @end lisp @node Using exiftool @section Using exiftool @cindex Using exiftool Make sure that the perl program exiftool is installed on your system. It is available at @uref{https://exiftool.org/}. Then set exiftool as the sole info method with: @lisp (setq emms-info-functions '(emms-info-exiftool)) @end lisp @node Using TagLib @section Using TagLib @cindex using taglib @file{emms-info-libtag.el} uses a tiny C shim (included in the src/ directory) program to take advantage of @uref{http://taglib.github.io/, TagLib}. The communication with the TagLib library is done via a tiny program written in C++ @file{emms-print-metadata.cpp}, which comes with Emms. To compile @file{emms-print-metadata} invoke: @command{make emms-print-metadata} The resultant binary will be installed when you invoke: @command{make install} as in @xref{Compiling Emms}. It is of course also possible to install only the @file{emms-print-metadata} binary where your system can find and execute it without installing all of Emms via the make command. Once the binary is available load @code{emms-info-libtag} and make it the @emph{only} info function with (note that if you have caching enabled you may have to delete the existing cache and repopulate it in order to see the TagLib data): @lisp (require 'emms-info-libtag) (setq emms-info-functions '(emms-info-libtag)) @end lisp @noindent @node Defining Info Methods @section Defining Info Methods @cindex defining info methods An info method essentially consists of a function which given an Emms track returns the appropriate info for that track. We can for example look at the predefined method for retrieving information about audio tracks in the Ogg format. The function @command{emms-info-ogginfo} provided by @file{emms-info-ogginfo.el} accepts an Emms track as a single argument and returns the appropriate information string. We then register our info function with Emms by adding it to the @var{emms-info-functions} list. The function will then be called at the right time to provide track info. @lisp (add-to-list 'emms-info-functions 'emms-info-ogginfo) @end lisp @c ------------------------------------------------------------------- @node Interactive Playlists @chapter Interactive Playlists @cindex Interactive Playlists Emms provides a visual, interactive playlist mode as well as the ability to use playlists without ever looking at then. This visual, interactive mode is called the `emms-playlist-mode' and is defined in @file{emms-playlist-mode.el}. The interactive playlist mode is enabled by default in the `emms-all' setup level. For more information about Emms setup levels see @xref{Setup}. @defun emms-playlist-mode-go Switch to the current emms-playlist buffer and use emms-playlist-mode. @end defun If you wish to make this the default Emms playlist mode, add the following to your @file{.emacs}. @lisp (setq emms-playlist-default-major-mode 'emms-playlist-mode) @end lisp The interactive playlist buffer shows the tracks in the current Emms playlist in the order in which they will be played. The current track will be highlighted. When in the interactive playlist mode we can perform different actions on the current playlist. @table @kbd @item a @findex emms-playlist-mode-add-contents Add files in the playlist at point to the current playlist buffer. If we are in the current playlist, make a new playlist buffer and set it as current. @item b @findex emms-playlist-set-playlist-buffer Set the current playlist buffer. @item n @findex emms-next Start playing the next track in the playlist. @item p @findex emms-next Start playing the previous track in the playlist. @item s @findex emms-stop Stop playing. @item P @findex emms-pause Pause. @item > @findex emms-seek-forward Seek ten seconds forward. @item < @findex emms-seek-backward Seek ten seconds backward. @item f @findex emms-show Describe the currently playing track in the minibuffer. @item c @findex emms-playlist-mode-center-current Display the current track in the center of the screen. @item RET @findex emms-playlist-mode-play-current-track Start playing the track under point. Note that this is also available with @kbd{}. @item SPC @findex scroll-up Scroll up a near full page. @item M-< @findex emms-playlist-mode-first Go to the first track in the playlist. @item M-> @findex emms-playlist-mode-last Go to the last track in the playlist. @item r @findex emms-random Go to a randomly selected track in the playlist. @item q @findex bury-buffer Put the interactive playlist buffer at the end of the list of all buffers. @item C-x C-s @findex emms-playlist-save Save the current playlist buffer to a file. By default, Emms will ask you for confirmation before overwriting an existing playlist. You can silently overwrite existing playlist by setting @var{emms-source-playlist-ask-before-overwrite} to nil. @item ? @findex describe-mode Describe the mode. @end table We can also edit the playlist using familiar GNU/Emacs commands: @table @kbd @item C-k @findex emms-playlist-mode-kill-track Remove the track under point from the playlist buffer. Also available using the @kbd{d} key. @item C-y @findex emms-playlist-mode-yank See the command @command{yank} @item C-w @findex emms-playlist-mode-kill See the command @command{kill-region} @item M-y @findex emms-playlist-mode-yank-pop See the command @command{yank-pop}. @item C-j @findex emms-playlist-mode-insert-newline Insert a newline at point. @end table We can use the regular GNU/Emacs killing and yanking commands to move and copy tracks in between playlist buffers. We can use the same commands to insert arbitrary text into the playlist buffers together with the playlist tracks. Text which is not a track is ignored by the program and can therefore be used to include titles and annotations within the playlist. @c ------------------------------------------------------------------- @node Markable Playlists @chapter Markable Playlists @cindex Markable Playlists The Markable Playlists provided by the file @file{emms-mark.el} are an alternative to the default interactive playlists, @xref{Interactive Playlists}. They allow marking tracks with keybindings familiar to users of dired. To enable the Markable Playlists you have to add @lisp (require 'emms-mark) @end lisp to your @file{.emacs}. Then you can activate @command{emms-mark-mode} by executing @command{M-x emms-mark-mode} in a playlist buffer. You can return to the default interactive playlist mode with @command{M-x emms-mark-mode-disable}. If you wish to make this the default Emms playlist mode, add the following to your @file{.emacs}. @lisp (setq emms-playlist-default-major-mode 'emms-mark-mode) @end lisp @table @kbd @item m @findex emms-mark-forward Marks the current track and sets point one line forward. If a prefix argument ARG is given, it will mark the next ARG tracks and set point accordingly. A negative argument marks backward. @item U @findex emms-mark-unmark-all Unmarks all tracks in the playlist. @item t @findex emms-mark-toggle Toggles mark on the current track. @item u @findex emms-mark-unmark-forward Unmarks same way as @command{emms-mark-forward} marks. @item % m @findex emms-mark-regexp Marks all tracks in the playlist matching the given regular expression. A prefix argument means to unmark them instead. @end table When tracks are marked you can operate on them: @table @kbd @item D @findex emms-mark-delete-marked-tracks Deletes the marked tracks from the playlist. @item K @findex emms-mark-kill-marked-tracks Deletes the marked tracks from the playlist and places them in the kill-ring, so that you can @command{yank} in into another playlist. @item W @findex emms-mark-copy-marked-tracks Adds the marked tracks to the kill-ring, so that you can @command{yank} them into another playlist. @end table emms-mark is also intent to provide a way for user to select tracks for other command to operate on them. Currently, @file{emms-tag-editor.el} uses the emms-mark to edit the tags of selected tracks. Two functions are useful for the elisp programer to handle marked tracks. @defun emms-mark-do-with-marked-track This function take a function to perform on all marked tracks. A optional argument `move-flag' to tell the function to move forward line after calling given function. If the given function didn't change position, the second argument should set to non-nil. @end defun @defun emms-mark-mapcar-marked-track This function is very similar to `emms-mark-do-with-marked-track' except it collects result of given function (that's why named with `mapcar'). @end defun @c ------------------------------------------------------------------- @node Extending Emms @chapter Extending Emms @cindex new players @cindex defining players @cindex new players, defining Emms introduces a high abstraction layer for playing music so you can customise it to your needs. @menu * New Player:: How to define a new player. * Simple Player for `play':: An example player using @command{play}. * More Complex Player:: Example of a complex player using @command{mpg321}. @end menu @node New Player @section New Player @cindex new player @cindex defining new players The file @file{emms-player-simple.el} defines some easy players to start with, but it shouldn't be hard to provide a function for your favourite player. We will start with an easy example that shows how we can use the @command{play} command under Unix to play our WAV files. @node Simple Player for `play' @section Simple Player for `play' @cindex simple player @cindex primitive player @cindex basic player Play is a very easy command line player for various format. If you want your emms to play WAV files just put the following lines in you @file{.emacs}: @lisp (require 'emms-player-simple) (define-emms-simple-player play '(file) "\\.wav$" "play") @end lisp @noindent Huh! Wasn't that easy? The macro function @command{define-emms-simple-player} takes a minimum of three arguments. The first argument (@emph{play} in our example) defines the name of the player. It's used to name the player functions. The second is a regexp, that defines which files to play with our player. @emph{\\.wav$} matches any filename ending with a dot and the string wav. The last argument is the actual command line command we use to play our files. You can also add the path but we just assume that the command is in your path. All arguments you add to these three are optional. They define the command line arguments you want to add to your argument. If you want to hear the wav file of your favourite artist in the most possible volume use the following line: @lisp (require 'emms-player-simple) (define-emms-simple-player play '(file) "\\artist-*.wav$" "play" "--volume=100") @end lisp @noindent Please notice that you have to add the arguments as strings! The command line tool you use for @command{define-emms-simple-player} has to take one song as argument and stop after playing that particular song. For any other concept you will need to customise emms a bit more... @node More Complex Player @section More Complex Player @cindex complex player @cindex advanced player The most players you use will be simple players so you don't need to read this chapter. But if you are curious how you can use (almost) every player in emms read further... In this chapter we will use mpg321 to construct a player that actually can pause a track, restart it and show rest time. We won't implement all of that, but after that chapter you will know how to define it. The command @command{define-emms-simple-player} is just a abstraction layer for @command{define-emms-player}, which is a little bit more complicated but much more powerful! @lisp (define-emms-player "emms-mpg321-remote" :start 'emms-mpg321-remote-start :stop 'emms-mpg321-remote-stop :playablep 'emms-mpg321-remote-playable-p) @end lisp @noindent So, that is almost all! @command{define-emms-player} takes a minimum of three arguments. The first is the name of the player. The rest are methods with functions to call. Three methods are required: start, stop and playable. Start says Emms how to start a track (sic!), stop how to stop a player and playablep should return non-nil if the player can play the track. So we just need these three functions to get our mpg321-remote: First we code the start function. We will check if there's a open process and start one otherwise. Then we send a string to the process with the filename and set a filter. @lisp (defun emms-mpg321-remote-start () (unless (get-process ``mpg321-remote'') (setq emms-mpg321-remote-process (start-process "mpg321-remote-process" "*mpg321*" "mpg321" "-R" "abc")) (process-send-string "mpg321-remote-process" (concat "l " (emms-track-name track))) (set-process-filter emms-mpg321-remote-process 'emms-mpg321-remote-filter))) @end lisp @noindent We need the filter, as mpg321-remote won't quit after playing the track as the simple player do. We wait until the process sends the output ``(at-sign)P 0'' (the signal of mpg321 that the song ended) to the filter and call emms-mpg321-remote-stop. @lisp (defun emms-mpg321-remote-filter (process output) (when (string-match "(at-sign)P 0" output) (emms-mpg321-remote-stop))) @end lisp @noindent @command{emms-mpg321-remote-stop} won't do anything interesting. It just test if there are other files to play and close the process otherwise. @lisp (defun emms-mpg321-remote-stop () (unless emms-playlist (process-send-string "mpg321-remote-process" "Q\n")) @end lisp @noindent And to make that a playable example I also added @command{emms-mpg321-remote-playablep}, which I really just steal from @file{emms-player-simple.el} @lisp (defun emms-mpg321-remote-playablep (track) "Return non-nil when we can play this track." (and (eq 'file (emms-track-type track)) @end lisp @noindent Now we have a ready player and we could add commands like @command{emms-mpg321-remote-pause} for example. @c ------------------------------------------------------------------- @node The Browser @chapter The Browser The Browser allows you to browse the metadata cache and add tracks to your playlist. It includes a powerful interactive mode. The Browser is defined in @file{emms-browser.el} and is included in the @command{emms-all} setup level. For more information about Emms setup levels see @xref{Setup}. You can also manually add the Browser to your Emms setup by loading it explicitly with: @lisp (require 'emms-browser) @end lisp To be properly useful, you should do M-x @command{emms-add-directory-tree} to all the files you own at least once so that the cache is fully populated. @menu * Browser Interface:: The interactive browser interface. * Filtering Tracks:: Displaying a subset of the tracks. * Displaying Covers:: Displaying album covers in the browser interface. * Changing Looks:: Changing the tree structure, display format and faces. @end menu @node Browser Interface @section Browser Interface The browser interface allows you to display and interact with your tracks in many different ways. There are a number of ways to start the browser. @defun emms-smart-browse 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. @end defun @defun emms-browse-by-artist Display the browser and order the tracks by artist. @end defun @defun emms-browse-by-album Display the browser and order the tracks by album. @end defun @defun emms-browse-by-genre Display the browser and order the tracks by genre. @end defun @defun emms-browse-by-year Display the browser and order the tracks by year. @end defun Once the Browser is displayed you can use it to managed your track collection and playlists. The Browser is interactive and has its own keybindings. @table @kbd @item C-j @kindex C-j (emms-browser) @findex emms-browser-add-tracks-and-play Add all tracks at point, and play the first added track. @item RET @kindex RET (emms-browser) @findex emms-browser-add-tracks Add all tracks at point. @item SPC @kindex SPC (emms-browser) @findex emms-browser-toggle-subitems Show or hide (kill) subitems under the current line. @item 1 @kindex 1 (emms-browser) @findex emms-browser-collapse-all Collapse everything. @item 2 @kindex 2 (emms-browser) @findex emms-browser-expand-to-level-2 Expand all top level items one level. @item 3 @kindex 3 (emms-browser) @findex emms-browser-expand-to-level-3 Expand all top level items two levels. @item 4 @kindex 4 (emms-browser) @findex emms-browser-expand-to-level-4 Expand all top level items three levels. @item C @kindex C (emms-browser) @findex emms-browser-clear-playlist Clear the playlist. @item E @kindex E (emms-browser) @findex emms-browser-expand-all Expand everything. @item d @kindex d (emms-browser) @findex emms-browser-view-in-dired View the current directory in dired. @item q @kindex q (emms-browser) @findex emms-browser-bury-buffer Bury the browser buffer. @item r @kindex r (emms-browser) @findex emms-browser-goto-random Jump to a random track. @item / @kindex / (emms-browser) @findex emms-isearch-buffer Isearch through the buffer. @item < @kindex < (emms-browser) @findex emms-browser-previous-filter Redisplay with the previous filter. @item > @kindex > (emms-browser) @findex emms-browser-next-filter Redisplay with the next filter. @item ? @kindex ? (emms-browser) @findex describe-mode See the Emacs documentation for the function. @item C-/ @kindex C-/ (emms-browser) @findex emms-playlist-mode-undo Undo the previous playlist action. @item @kindex (emms-browser) @findex emms-browser-add-tracks-and-play Add all tracks at point, and play the first added track. @item @kindex (emms-browser) @findex emms-browser-prev-non-track Jump to the previous non-track element. @item @kindex (emms-browser) @findex emms-browser-next-non-track Jump to the next non-track element. @item s A @kindex s A (emms-browser) @findex emms-browser-search-by-album Search the collection by album. @item s a @kindex s a (emms-browser) @findex emms-browser-search-by-artist Search the collection by artist. @item s s @kindex s s (emms-browser) @findex emms-browser-search-by-names Search the collection by names. @item s t @kindex s t (emms-browser) @findex emms-browser-search-by-title Search the collection by title. @item b 1 @kindex b 1 (emms-browser) @findex emms-browse-by-artist Browse the collection by artist. @item b 2 @kindex b 2 (emms-browser) @findex emms-browse-by-album Browse the collection by album. @item b 3 @kindex b 3 (emms-browser) @findex emms-browse-by-genre Browse the collection by genre. @item b 4 @kindex b 4 (emms-browser) @findex emms-browse-by-year Browse the collection by year. @item W a p @kindex W a p (emms-browser) @findex emms-browser-lookup-album-on-pitchfork Lookup the album using Pitchfork. @item W a w @kindex W a w (emms-browser) @findex emms-browser-lookup-album-on-wikipedia Lookup the album using Wikipedia. @end table @node Filtering Tracks @section Filtering Tracks If you want to display a subset of your collection (such as a directory of 80s music, only avi files, etc.) then you can extend the Browser by defining ``filters''. Show everything: @lisp (emms-browser-make-filter "all" 'ignore) @end lisp Set "all" as the default filter: @lisp (emms-browser-set-filter (assoc "all" emms-browser-filters)) @end lisp Show all files (no streamlists, etc): @lisp (emms-browser-make-filter "all-files" (emms-browser-filter-only-type 'file)) @end lisp Show only tracks in one folder: @lisp (emms-browser-make-filter "80s" (emms-browser-filter-only-dir "~/Mp3s/80s")) @end lisp Show all tracks played in the last month: @lisp (emms-browser-make-filter "last-month" (emms-browser-filter-only-recent 30)) @end lisp After executing the above commands, you can use M-x emms-browser-show-all, emms-browser-show-80s, etc to toggle between different collections. Alternatively you can use '<' and '>' to cycle through the available filters. The second argument to make-filter is a function which returns t if a single track should be filtered. You can write your own filter functions to check the type of a file, etc. Show only tracks not played in the last year: @lisp (emms-browser-make-filter "not-played" (lambda (track) (not (funcall (emms-browser-filter-only-recent 365) track)))) @end lisp Show all files that are not in the pending directory: @lisp (emms-browser-make-filter "all" (lambda (track) (or (funcall (emms-browser-filter-only-type 'file) track) (not (funcall (emms-browser-filter-only-dir "~/Media/pending") track))))) @end lisp @node Displaying Covers @section Displaying Covers The browser will attempt to display cover images if they're 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. 'emms-browser-cache-thumbnail' might be everytime a cover is queried, so to help with performance you can also set @var{emms-browser-covers} to 'emms-browser-cache-thumbnail-async'. The latter is like the former except that it caches queries: every subsequent query will be much faster. The drawback is that it won't see changes made to covers after the first query. To force-refresh the thumbnail cache, you can run 'emms-browser-clear-cache-hash'. 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 number ``0.0''. To show a 'no cover' image for albums which don't have a cover, add the following code to your .emacs: @lisp (setq emms-browser-default-covers (list "/path/to/cover_small.jpg" nil nil) @end lisp The medium and large images can be set as well. You can download an example @uref{http://repose.cx/cover_small.jpg, `no cover' image}. @node Changing Looks @section Changing Looks The Browser's look can be customised. You can change the way the tree structure looks, the display format and display faces. @subheading Changing Tree Structure You can change the way the tree is displayed by modifying the function @command{emms-browser-next-mapping-type}. The following code displays artist->track instead of artist->album->track when you switch to the 'singles' filter: @lisp (defadvice emms-browser-next-mapping-type (after no-album (current-mapping)) (when (eq ad-return-value 'info-album) (setq ad-return-value 'info-title))) @end lisp @lisp (defun toggle-album-display () (if (string= emms-browser-current-filter-name "singles") (ad-activate 'emms-browser-next-mapping-type) (ad-deactivate 'emms-browser-next-mapping-type))) (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 playlist. You can customize these if you wish. @var{emms-browser-default-format} controls the format to use when no other format has been explicitly defined. By default, only track and albums deviate from the default. To customise the format of a particular type, find the name of the field you want to use (eg `info-artist', `info-title', etc), and insert that into emms-browser--format or emms-browser-playlist--format. For example, if you wanted to remove track numbers from tracks in both the browser and playlist, you could do: @lisp (defvar emms-browser-info-title-format "%i%n") (defvar emms-browser-playlist-info-title-format emms-browser-info-title-format) @end lisp The format specifiers available include: @itemize @w{} @item %i indent relative to the current level @item %n the value of the item - eg -info-artist might be ``pink floyd'' @item %y the album year @item %A the album name @item %a the artist name of the track @item %t the title of the track @item %T the track number @item %cS a small album cover @item %cM a medium album cover @item %cL a big album cover @end itemize Note that if you use track-related items like %t, it will take the data from the first track. @subheading Changing Display Faces The faces used to display the various fields are also customizable. They are in the format emms-browser--face, where type is one of "year/genre", "artist", "album" or "track". Note that faces lack the initial "info-" part. For example, to change the artist face, type M-x @command{customize-face} @command{emms-browser-artist-face}. @c ------------------------------------------------------------------- @node Sorting Playlists @chapter Sorting Playlists @cindex sort @cindex track order The `emms-playlist-sort' module, defined in the @file{emms-playlist-sort.el} package provides functions for sorting Emms playlists, as well as keyboard shortcuts for invoking the functions in the playlist buffer. Most of the functions will sort in reverse order if the command is preceded by a prefix. `emms-playlist-sort' can be loaded by invoking: @lisp (require 'emms-playlist-sort) @end lisp @defun emms-playlist-sort-by-info-artist Sort by artist name. @end defun @defun emms-playlist-sort-by-play-count Sort by number of times the track has been played. @end defun @defun emms-playlist-sort-by-info-album Sort by album name. @end defun @defun emms-playlist-sort-by-last-played Sort by time the track was played last. @end defun @defun emms-playlist-sort-by-info-title Sort by track title. @end defun @defun emms-playlist-sort-by-file-extension Sort by filename extension. @end defun @defun emms-playlist-sort-by-info-performer Sort by performer name. @end defun @defun emms-playlist-sort-by-info-year Sort by year. @end defun @defun emms-playlist-sort-by-info-note Sort by track notes. @end defun @defun emms-playlist-sort-by-info-composer Sort by composer. @end defun @defun emms-playlist-sort-by-name Sort by track name. @end defun @defun emms-playlist-sort-by-file-mtime Sort by file mtime. @end defun @c ------------------------------------------------------------------- @node Persistent Playlists @chapter Persistent Playlists The Emms module @file{emms-history.el} makes playlists persistent over emacs sessions. To make use of this feature put this into your ~/.emacs. @lisp (require 'emms-history) @end lisp When you kill emacs all playlists will be saved in the file given by the variable: @defopt emms-history-file The file to save playlists in. It defaults to "~/.emacs.d/emms-history". @end defopt After you started up emacs again, you can restore all saved playlists with this function. @defun emms-history-load Restore all playlists in `emms-history-file'. @end defun If that should be done automatically on each startup, put these lines into your ~/.emacs. @lisp (require 'emms-history) (emms-history-load) @end lisp Normally @code{emms-history} only restores playlists. If you want it to start playback afterwards, you can tweak this variable. @defopt emms-history-start-playing If non-nil emms starts playing the current track after `emms-history-load' was invoked. The default value is nil. @end defopt @c ------------------------------------------------------------------- @node Editing Tracks @chapter Editing Tracks @cindex track editor 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 `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 mark tracks). The track's tag informations are listed in a special buffer `*Emms-TAGS*' in text format. Field names are marked in bold face and are not editable. Any tag information is placed behind an equal sign and is changable. A special field `name' is the track's file name. If any change is made in this field, the track's file will be renamed to the new name. When you finished editing the tag infos use @kbd{C-c C-c} (which calls @code{emms-tag-editor-submit-and-exit}) to submit the changes and close the `*Emms-TAGS*' buffer. There are a few commands to perform changes on all tracks. @defun emms-tag-editor-set-all tag value Set TAG to VALUE in all tracks. If transient-mark-mode is turned on, you can apply the command to a selected region. If `transient-mark-mode' is on and the mark is active, the changes will only take effect on the tracks in the region. @end defun @defun emms-tag-editor-replace-in-tag tag from to Query and replace text in selected TAG. For example, if the info-title tag is selected, then only perform replacement in title tags. If `transient-mark-mode' is on and the mark is active, the changes will only take effect on the tracks in the region. @end defun @defun emms-tag-editor-transpose-tag tag1 tag2 Transpose value of TAG1 and TAG2. If `transient-mark-mode' is on and the mark is active, the changes will only take effect on the tracks in the region. @end defun @defun emms-tag-editor-submit arg Make modified tags take affect. With prefix argument, bury the tag edit buffer. @end defun If you want to extend the tag editor to work with file formats other than `mp3' and `ogg', have a look at these variables. @defvr {Variable} emms-tag-editor-formats This variable determine how to insert track fields to `emms-tag-editor-edit-buffer'. Emms tag info editable fields is usually determined by the extension of track name. The variable `emms-tag-editor-tags' contains all tags that emms track may have. A single charactar is assigned to the tag to make the `emms-tag-editor-formats' easier to generate. @end defvr @defvr {Variable} emms-tag-editor-tagfile-functions To write tags to track file, an extern program should specified in this variable. @end defvr @heading Renaming Files The tag editor is also capable to rename the file of the track at point or all files of the marked tracks according to the value this variable. @defopt emms-tag-editor-rename-format When `emms-tag-editor-rename' is invoked the track's file will be renamed according this format specification. The file extension will be added automatically. It uses the format specs defined in @code{emms-tag-editor-tags}. The default value is "%a - %l - %n - %t", so that files are named - - - .<extension> after renaming. @end defopt To perform the renaming put point on the track you want to rename or mark some tracks. Then hit @kbd{R} which calls this function: @defun emms-tag-editor-rename Rename the file corresponding to track at point or all marked tracks according to the value of @code{emms-tag-editor-rename-format}. @end defun @c ------------------------------------------------------------------- @node Emms Mode Line @chapter Emms Mode Line @cindex mode line @cindex display emms information We can display information about the currenty playing track on the Emacs mode line using the package `emms-mode-line' which is provided by the file @file{emms-mode-line.el}. To activate this feature invoke: @lisp (require 'emms-mode-line) (emms-mode-line 1) @end lisp It is also possible to display the amount of time a track has been playing. This feature is defined in the `emms-playing-time' package which is provided by the file @file{emms-playing-time.el}. To use this feature invoke: @lisp (require 'emms-playing-time) (emms-playing-time 1) @end lisp Note: `(emms-playing-time -1)' will disable emms-playing-time module completely, and is not recommended. (since some other emms modules may rely on it) Instead, to toggle displaying playing time on mode line, one could call `emms-playing-time-enable-display' and `emms-playing-time-disable-display'." @defun emms-playing-time-enable-display Display playing time on mode line. @end defun @defun emms-playing-time-disable-display Remove playing time from mode line. @end defun @c ------------------------------------------------------------------- @node Limiting @chapter Limiting @cindex limiting @cindex playlist The package `emms-playlist-limit', provided by @file{emms-playlist-limit.el}, allows creating a new playlist derived from the playlist in the current buffer. For instance, it is possible to create a new playlist containing only a certain artist or genre from the playlist in the current buffer. If the playlist in the current buffer is the emms current playlist then the derived playlist becomes current. @table @kbd @item / a @kindex / a @findex emms-playlist-limit-to-info-artist Create a new playlist buffer and populate it with tracks whose artist info field matches the given regular expression (default: the artist info field of the track at point). @item / b @kindex / b @findex emms-playlist-limit-to-info-album Create a new playlist buffer and populate it with tracks whose album info field matches the given regular expression (default: the album info field of the track at point). @item / c @kindex / c @findex emms-playlist-limit-to-info-composer Create a new playlist buffer and populate it with tracks whose composer info field matches the given regular expression (default: the composer info field of the track at point). @item / d @kindex / d @findex emms-playlist-limit-to-description Create a new playlist buffer and populate it with tracks whose track description matches the given regular expression (default: the track description of the track at point). @item / g @kindex / g @findex emms-playlist-limit-to-info-genre Create a new playlist buffer and populate it with tracks whose genre info field matches the given regular expression (default: the genre info field of the track at point). @item / n @kindex / n @findex emms-playlist-limit-to-name Create a new playlist buffer and populate it with tracks whose name matches the given regular expression (default: the name of the track at point). @item / p @kindex / p @findex emms-playlist-limit-to-info-performer Create a new playlist buffer and populate it with tracks whose performer info field matches the given regular expression (default: the performer info field of the track at point). @item / t @kindex / t @findex emms-playlist-limit-to-info-title Create a new playlist buffer and populate it with tracks whose title info field matches the given regular expression (default: the title info field of the track at point). @item / y @kindex / y @findex emms-playlist-limit-to-info-year Create a new playlist buffer and populate it with tracks whose year info field matches the given regular expression (default: the year info field of the track at point). @item / / @kindex / / @findex emms-playlist-limit-to-all Switch to the original playlist buffer (if it still exists). @end table @c ------------------------------------------------------------------- @node Music Player Daemon @chapter Music Player Daemon @cindex music player daemon @cindex remote interface @cindex mpd Emms provides an interface to the @uref{http://www.musicpd.org/, Music Player Daemon}(MusicPD) software. The package is called `emms-player-mpd' and is provided by the file @file{emms-player-mpd.el}. The advantages of using MusicPD as an Emms backend include the following. @itemize @bullet @item minimal CPU usage @item fast access of track information @item optional crossfade @end itemize @subheading Setup To load `emms-player-mpd' invoke: @lisp (require 'emms-player-mpd) @end lisp Set the variables @var{emms-player-mpd-server-name} and @var{emms-player-mpd-server-port} to the location and port (respectively) of your MusicPD server. For example: @lisp (setq emms-player-mpd-server-name "localhost") (setq emms-player-mpd-server-port "6600") @end lisp If your MusicPD setup requires a password, you will to set @var{emms-player-mpd-server-password} as follows. @lisp (setq emms-player-mpd-server-password "mypassword") @end lisp To get track information from MusicPD, invoke the following: @lisp (add-to-list 'emms-info-functions 'emms-info-mpd) @end lisp Adding `emms-player-mpd' to your Emms player list is accomplished by invoking: @lisp (add-to-list 'emms-player-list 'emms-player-mpd) @end lisp Unless your MusicPD is configured to use absolute file names, you must set the emms-player-mpd-music-directory variable to the value of 'music_directory' in your MusicPD configuration. There are additional options available as well, but the defaults should be sufficient for most uses. Once you've done the above, run the @kbd{M-x emms-cache-set-from-mpd-all} command to fill the Emms cache with the contents of your MusicPD database. The music in your MusicPD database should then be accessible via the Emms browser. You can set @var{emms-player-mpd-sync-playlist} to nil if your master Emms playlist contains only stored playlists. @subheading Commands provided @defun emms-player-mpd-connect Connect to MusicPD and retrieve its current playlist. Afterward, the status of MusicPD will be tracked. @end defun @defun emms-player-mpd-disconnect Terminate the MusicPD client process and disconnect from MusicPD. @end defun @defun emms-player-mpd-show &optional insertp Describe the current Emms track in the minibuffer. If INSERTP is non-nil, insert the description into the current buffer instead. This function uses @var{emms-show-format} to format the current track. It differs from @command{emms-show} in that it asks MusicPD for the current track, rather than Emms. @end defun @subsubheading Updating the MusicPD database @defun emms-player-mpd-update-directory dir Cause the tracks in DIR to be updated in the MusicPD database. @end defun @defun emms-player-mpd-update-all Cause all tracks in the MusicPD music directory to be updated in the MusicPD database. @end defun @subsubheading emms-cache.el integration @defun emms-cache-set-from-mpd-directory dir Dump all MusicPD data from DIR into the Emms cache. This is useful to do when you have recently acquired new music. @end defun @defun emms-cache-set-from-mpd-all Dump all MusicPD data into the Emms cache. This is useful to do once, just before using emms-browser.el, in order to prime the cache. @end defun @subsubheading emms-volume.el integration To activate this, add the following to your .emacs. @lisp (require 'emms-volume) (setq emms-volume-change-function 'emms-volume-mpd-change) @end lisp @c ------------------------------------------------------------------- @node Lyrics @chapter Lyrics @cindex lyrics We can display the lyrics of a song in time with the music using the `emms-lyrics' package provided by the file @file{emms-lyrics.el}. The lyrics files should have the extention ``.lrc'', and can be placed under either the same directory as the music files or @var{emms-lyrics-dir}. To add this feature we invoke: @lisp (require 'emms-lyrics) (emms-lyrics 1) @end lisp There are a number of variables we can set to define the way that `emms-lyrics' behaves, we can set these directly or by using the Customize feature in Emacs. @defvr {User Option} emms-lyrics-display-on-minibuffer If non-nil, display lyrics on minibuffer. @end defvr @defvr {User Option} emms-lyrics-display-on-modeline If non-nil, display lyrics on modeline. @end defvr @defvr {User Option} emms-lyrics-dir Local lyrics repository. @command{emms-lyrics-find-lyric} will look for lyrics in current directory(i.e., same as the music file) and this directory. @end defvr @defvr {User Option} emms-lyrics-display-format Format for displaying lyrics. "%s" will be replaced by the lyrics string. @end defvr @defvr {User Option} emms-lyrics-coding-system Coding system used in the output of lyrics. @end defvr @defvr {User Option} emms-lyrics-scroll-p Non-nil value will enable lyrics scrolling. @end defvr @defvr {User Option} emms-lyrics-scroll-timer-interval Interval between scroller timers. The shorter, the faster. @end defvr We can control `emms-lyrics' with the help of the following functions: @defun emms-lyrics-start Start displaying lyrics. @end defun @defun emms-lyrics-stop Stop displaying lyrics. @end defun @defun emms-lyrics-toggle-display-on-minibuffer Toggle display lyrics on minibufer. @end defun @defun emms-lyrics-toggle-display-on-modeline Toggle display lyrics on mode line. @end defun @defun emms-lyrics-enable Enable displaying Emms lyrics. @end defun @defun emms-lyrics-disable Disable displaying Emms lyrics. @end defun @defun emms-lyrics-toggle Toggle displaying Emms lyrics. @end defun @c ------------------------------------------------------------------- @node Volume @chapter Volume @cindex volume We can use the `emms-volume' package, as provided by the @file{emms-volume.el} file, to manipulate the volume. @defopt emms-volume-change-amount The amount to use when raising or lowering the volume using the emms-volume interface. This should be a positive integer. @end defopt @defun emms-volume-raise Increase the volume. @end defun @defun emms-volume-lower Decrease the volume. @end defun If you feel like binding those two functions to global keys --- don't do it or you'll miss the convenience of `emms-volume-minor-mode'. Instead, bind the following two commands to some keys that you like. @defun emms-volume-mode-plus Raise volume and enable or extend the `emms-volume-minor-mode' timeout. @end defun @defun emms-volume-mode-minus Lower volume and enable or extend the `emms-volume-minor-mode' timeout. @end defun Example: @lisp (global-set-key (kbd "C-c +") 'emms-volume-mode-plus) (global-set-key (kbd "C-c -") 'emms-volume-mode-minus) @end lisp Whenever you use one of these keys or call these functions with @kbd{M-x}, Emms will be put into `emms-volume-minor-mode' for a short period defined by `emms-volume-mode-timeout'. @defopt emms-volume-mode-timeout The timeout in amount of seconds used by `emms-volume-minor-mode'. @end defopt In this interval you can raise/lower the volume simply by pressing @kbd{+} or @kbd{-}, which will also reset the timer to its initial value. So instead of pressing @kbd{C-c +} six times to increase volume by six steps of @code{emms-volume-change-amount}, you would simply type @kbd{C-c + + + + + +}. Emms can change volume with amixer, mpd, PulseAudio and mixerctl out of the box, see @var{emms-volume-change-function}. @c ------------------------------------------------------------------- @node Streaming Audio @chapter Streaming Audio @cindex streaming audio @cindex internet radio Emms is a great way to play streaming audio and internet radio. It is possible to add streaming playlists and URLs to any playlist, but Emms also comes with a built-in, eclectic list of streaming audio stations. @footnote{Emms has no affiliation of any kind with the streaming audio stations included, nor is their inclusion an endorsement of these stations. Instead, this is a collection of stations submitted to the project over the years by people who enjoy Emms. We hope you will enjoy them too, and invite you to send in your suggestions to add to the list.} The @file{emms-streams.el} package provides the command @command{emms-streams}. Invoking @command{emms-streams} will pull up an Emms playlist buffer and populate it with the built-in list of streaming audio sources. @c ------------------------------------------------------------------- @node APE / FLAC Commands @chapter APE / FLAC Commands Often, a single APE or FLAC file contains a complete ablum. We can still play next or previous track in the ablum with the help of @file{emms-cue.el} package, provided there is a corresponding cue sheet file. This package also defines @code{emms-info-cueinfo} for retreiving the track information for APE / FLAC itself. To load @file{emms-cue.el}: @lisp (require 'emms-cue) (add-to-list 'emms-info-functions 'emms-info-cueinfo) @end lisp @defun emms-cue-next Play next track from .cue file @end defun @defun emms-cue-previous Play previous track from .cue file @end defun @c ------------------------------------------------------------------- @node Bookmarks @chapter Bookmarks Emms can save a ``temporal bookmark'' in a media file via emms-bookmarks. The file @file{emms-bookmarks.el} provides the package emms-bookmarks. While some media is playing, invoking @kbd{M-x emms-bookmarks-add} will first pause the playback and then prompt for a name describing the bookmark. Tracks can have multiple bookmarks associated with them. To jump to the next and previous bookmarks in the current track invoke @kbd{M-x emms-bookmarks-next} and @kbd{M-x emms-bookmarks-prev} respectively. To clear all of the bookmarks for the current track invoke @kbd{M-x emms-bookmarks-clear}. @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 @cindex GNU FM @url{https://www.gnu.org/software/gnufm/, GNU FM} is free software for running music community websites. It was created for the music community site, @url{http://libre.fm/, Libre.fm}. Emms can send track information, and stream music from GNU FM servers using @file{emms-librefm-scrobbler.el} and @file{emms-librefm-stream.el}, respectively. Emms is configured by default to use @url{http://libre.fm/, Libre.fm}, but can work with any GNU FM server by configuring the variable @var{emms-librefm-scrobbler-handshake-url} to the URL of the GNU FM server. The recommended way of providing your credentials to the GNU FM server is by using an authinfo file. Add authentication to your auth-info file, typically @file{~/.authinfo.gpg}, as: @smallexample machine libre.fm login USERNAME password PASSWORD @end smallexample If you are using some other server than libre.fm, change ``@samp{libre.fm}'' to match @var{emms-librefm-scrobbler-handshake-url}. Alternatively, you can save the password in plaintext in your init-file by setting these variables: @lisp (setq emms-librefm-scrobbler-username "USERNAME" emms-librefm-scrobbler-password "PASSWORD") @end lisp @menu * Uploading Track Information:: How to submit listened track information. * GNU FM Streaming:: Streaming music from a GNU FM server. @end menu @node Uploading Track Information @section Uploading Track Information GNU FM servers, such as Libre.fm can optionally store a user's listening habits using information sent to the website's server from the Emms. By utilizing the records of users' listening habits, the website aims to be able to recommend music to users by analyzing their musical taste. Load the feature into Emms with: @lisp (require 'emms-librefm-scrobbler) @end lisp This feature can also be enabled via @xref{Setup}, in the `emms-all' setup level. Enable uploading the details of the tracks Emms plays to the GNU FM server with @kbd{emms-librefm-scrobbler-enable}. The track's details will be uploaded to the server when the track's playback ends. You can disable this behavior with @kbd{emms-librefm-scrobbler-disable}. @node GNU FM Streaming @section GNU FM Streaming If the GNU FM server provides a streaming music service you can take advantage of it by loading: @lisp (require 'emms-librefm-stream) @end lisp This feature can also be enabled via @xref{Setup}, in the `emms-all' setup level. Then invoke @kbd{emms-librefm-stream} and enter the URL of the station you wish to listen to, for example ``librefm://globaltags/Classical''. @c including the relevant licenses @include gpl.texi @include fdl.texi @node Concept Index @unnumbered Concept Index @printindex cp @node Function Index @unnumbered Function Index @printindex fn @node Variable Index @unnumbered Variable Index @printindex vr @node Keybinding Index @unnumbered Keybinding Index @printindex ky @bye �����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������emms-6.00/doc/fdl.texi������������������������������������������������������������������������������0000664�0001750�0001750�00000051006�13746063641�013017� 0����������������������������������������������������������������������������������������������������ustar �yrk�����������������������������yrk��������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������@node The GNU FDL, Concept Index, Copying, Top @chapter GNU Free Documentation License @cindex FDL, GNU Free Documentation License @center Version 1.2, November 2002 @display Copyright @copyright{} 2000,2001,2002 Free Software Foundation, Inc. 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA Everyone is permitted to copy and distribute verbatim copies of this license document, but changing it is not allowed. @end display @enumerate 0 @item PREAMBLE The purpose of this License is to make a manual, textbook, or other functional and useful document @dfn{free} in the sense of freedom: to assure everyone the effective freedom to copy and redistribute it, with or without modifying it, either commercially or noncommercially. Secondarily, this License preserves for the author and publisher a way to get credit for their work, while not being considered responsible for modifications made by others. This License is a kind of ``copyleft'', which means that derivative works of the document must themselves be free in the same sense. It complements the GNU General Public License, which is a copyleft license designed for free software. We have designed this License in order to use it for manuals for free software, because free software needs free documentation: a free program should come with manuals providing the same freedoms that the software does. But this License is not limited to software manuals; it can be used for any textual work, regardless of subject matter or whether it is published as a printed book. We recommend this License principally for works whose purpose is instruction or reference. @item APPLICABILITY AND DEFINITIONS This License applies to any manual or other work, in any medium, that contains a notice placed by the copyright holder saying it can be distributed under the terms of this License. Such a notice grants a world-wide, royalty-free license, unlimited in duration, to use that work under the conditions stated herein. The ``Document'', below, refers to any such manual or work. Any member of the public is a licensee, and is addressed as ``you''. You accept the license if you copy, modify or distribute the work in a way requiring permission under copyright law. A ``Modified Version'' of the Document means any work containing the Document or a portion of it, either copied verbatim, or with modifications and/or translated into another language. A ``Secondary Section'' is a named appendix or a front-matter section of the Document that deals exclusively with the relationship of the publishers or authors of the Document to the Document's overall subject (or to related matters) and contains nothing that could fall directly within that overall subject. (Thus, if the Document is in part a textbook of mathematics, a Secondary Section may not explain any mathematics.) The relationship could be a matter of historical connection with the subject or with related matters, or of legal, commercial, philosophical, ethical or political position regarding them. The ``Invariant Sections'' are certain Secondary Sections whose titles are designated, as being those of Invariant Sections, in the notice that says that the Document is released under this License. If a section does not fit the above definition of Secondary then it is not allowed to be designated as Invariant. The Document may contain zero Invariant Sections. If the Document does not identify any Invariant Sections then there are none. The ``Cover Texts'' are certain short passages of text that are listed, as Front-Cover Texts or Back-Cover Texts, in the notice that says that the Document is released under this License. A Front-Cover Text may be at most 5 words, and a Back-Cover Text may be at most 25 words. A ``Transparent'' copy of the Document means a machine-readable copy, represented in a format whose specification is available to the general public, that is suitable for revising the document straightforwardly with generic text editors or (for images composed of pixels) generic paint programs or (for drawings) some widely available drawing editor, and that is suitable for input to text formatters or for automatic translation to a variety of formats suitable for input to text formatters. A copy made in an otherwise Transparent file format whose markup, or absence of markup, has been arranged to thwart or discourage subsequent modification by readers is not Transparent. An image format is not Transparent if used for any substantial amount of text. A copy that is not ``Transparent'' is called ``Opaque''. Examples of suitable formats for Transparent copies include plain @sc{ascii} without markup, Texinfo input format, La@TeX{} input format, @acronym{SGML} or @acronym{XML} using a publicly available @acronym{DTD}, and standard-conforming simple @acronym{HTML}, PostScript or @acronym{PDF} designed for human modification. Examples of transparent image formats include @acronym{PNG}, @acronym{XCF} and @acronym{JPG}. Opaque formats include proprietary formats that can be read and edited only by proprietary word processors, @acronym{SGML} or @acronym{XML} for which the @acronym{DTD} and/or processing tools are not generally available, and the machine-generated @acronym{HTML}, PostScript or @acronym{PDF} produced by some word processors for output purposes only. The ``Title Page'' means, for a printed book, the title page itself, plus such following pages as are needed to hold, legibly, the material this License requires to appear in the title page. For works in formats which do not have any title page as such, ``Title Page'' means the text near the most prominent appearance of the work's title, preceding the beginning of the body of the text. A section ``Entitled XYZ'' means a named subunit of the Document whose title either is precisely XYZ or contains XYZ in parentheses following text that translates XYZ in another language. (Here XYZ stands for a specific section name mentioned below, such as ``Acknowledgements'', ``Dedications'', ``Endorsements'', or ``History''.) To ``Preserve the Title'' of such a section when you modify the Document means that it remains a section ``Entitled XYZ'' according to this definition. The Document may include Warranty Disclaimers next to the notice which states that this License applies to the Document. These Warranty Disclaimers are considered to be included by reference in this License, but only as regards disclaiming warranties: any other implication that these Warranty Disclaimers may have is void and has no effect on the meaning of this License. @item VERBATIM COPYING You may copy and distribute the Document in any medium, either commercially or noncommercially, provided that this License, the copyright notices, and the license notice saying this License applies to the Document are reproduced in all copies, and that you add no other conditions whatsoever to those of this License. You may not use technical measures to obstruct or control the reading or further copying of the copies you make or distribute. However, you may accept compensation in exchange for copies. If you distribute a large enough number of copies you must also follow the conditions in section 3. You may also lend copies, under the same conditions stated above, and you may publicly display copies. @item COPYING IN QUANTITY If you publish printed copies (or copies in media that commonly have printed covers) of the Document, numbering more than 100, and the Document's license notice requires Cover Texts, you must enclose the copies in covers that carry, clearly and legibly, all these Cover Texts: Front-Cover Texts on the front cover, and Back-Cover Texts on the back cover. Both covers must also clearly and legibly identify you as the publisher of these copies. The front cover must present the full title with all words of the title equally prominent and visible. You may add other material on the covers in addition. Copying with changes limited to the covers, as long as they preserve the title of the Document and satisfy these conditions, can be treated as verbatim copying in other respects. If the required texts for either cover are too voluminous to fit legibly, you should put the first ones listed (as many as fit reasonably) on the actual cover, and continue the rest onto adjacent pages. If you publish or distribute Opaque copies of the Document numbering more than 100, you must either include a machine-readable Transparent copy along with each Opaque copy, or state in or with each Opaque copy a computer-network location from which the general network-using public has access to download using public-standard network protocols a complete Transparent copy of the Document, free of added material. If you use the latter option, you must take reasonably prudent steps, when you begin distribution of Opaque copies in quantity, to ensure that this Transparent copy will remain thus accessible at the stated location until at least one year after the last time you distribute an Opaque copy (directly or through your agents or retailers) of that edition to the public. It is requested, but not required, that you contact the authors of the Document well before redistributing any large number of copies, to give them a chance to provide you with an updated version of the Document. @item MODIFICATIONS You may copy and distribute a Modified Version of the Document under the conditions of sections 2 and 3 above, provided that you release the Modified Version under precisely this License, with the Modified Version filling the role of the Document, thus licensing distribution and modification of the Modified Version to whoever possesses a copy of it. In addition, you must do these things in the Modified Version: @enumerate A @item Use in the Title Page (and on the covers, if any) a title distinct from that of the Document, and from those of previous versions (which should, if there were any, be listed in the History section of the Document). You may use the same title as a previous version if the original publisher of that version gives permission. @item List on the Title Page, as authors, one or more persons or entities responsible for authorship of the modifications in the Modified Version, together with at least five of the principal authors of the Document (all of its principal authors, if it has fewer than five), unless they release you from this requirement. @item State on the Title page the name of the publisher of the Modified Version, as the publisher. @item Preserve all the copyright notices of the Document. @item Add an appropriate copyright notice for your modifications adjacent to the other copyright notices. @item Include, immediately after the copyright notices, a license notice giving the public permission to use the Modified Version under the terms of this License, in the form shown in the Addendum below. @item Preserve in that license notice the full lists of Invariant Sections and required Cover Texts given in the Document's license notice. @item Include an unaltered copy of this License. @item Preserve the section Entitled ``History'', Preserve its Title, and add to it an item stating at least the title, year, new authors, and publisher of the Modified Version as given on the Title Page. If there is no section Entitled ``History'' in the Document, create one stating the title, year, authors, and publisher of the Document as given on its Title Page, then add an item describing the Modified Version as stated in the previous sentence. @item Preserve the network location, if any, given in the Document for public access to a Transparent copy of the Document, and likewise the network locations given in the Document for previous versions it was based on. These may be placed in the ``History'' section. You may omit a network location for a work that was published at least four years before the Document itself, or if the original publisher of the version it refers to gives permission. @item For any section Entitled ``Acknowledgements'' or ``Dedications'', Preserve the Title of the section, and preserve in the section all the substance and tone of each of the contributor acknowledgements and/or dedications given therein. @item Preserve all the Invariant Sections of the Document, unaltered in their text and in their titles. Section numbers or the equivalent are not considered part of the section titles. @item Delete any section Entitled ``Endorsements''. Such a section may not be included in the Modified Version. @item Do not retitle any existing section to be Entitled ``Endorsements'' or to conflict in title with any Invariant Section. @item Preserve any Warranty Disclaimers. @end enumerate If the Modified Version includes new front-matter sections or appendices that qualify as Secondary Sections and contain no material copied from the Document, you may at your option designate some or all of these sections as invariant. To do this, add their titles to the list of Invariant Sections in the Modified Version's license notice. These titles must be distinct from any other section titles. You may add a section Entitled ``Endorsements'', provided it contains nothing but endorsements of your Modified Version by various parties---for example, statements of peer review or that the text has been approved by an organization as the authoritative definition of a standard. You may add a passage of up to five words as a Front-Cover Text, and a passage of up to 25 words as a Back-Cover Text, to the end of the list of Cover Texts in the Modified Version. Only one passage of Front-Cover Text and one of Back-Cover Text may be added by (or through arrangements made by) any one entity. If the Document already includes a cover text for the same cover, previously added by you or by arrangement made by the same entity you are acting on behalf of, you may not add another; but you may replace the old one, on explicit permission from the previous publisher that added the old one. The author(s) and publisher(s) of the Document do not by this License give permission to use their names for publicity for or to assert or imply endorsement of any Modified Version. @item COMBINING DOCUMENTS You may combine the Document with other documents released under this License, under the terms defined in section 4 above for modified versions, provided that you include in the combination all of the Invariant Sections of all of the original documents, unmodified, and list them all as Invariant Sections of your combined work in its license notice, and that you preserve all their Warranty Disclaimers. The combined work need only contain one copy of this License, and multiple identical Invariant Sections may be replaced with a single copy. If there are multiple Invariant Sections with the same name but different contents, make the title of each such section unique by adding at the end of it, in parentheses, the name of the original author or publisher of that section if known, or else a unique number. Make the same adjustment to the section titles in the list of Invariant Sections in the license notice of the combined work. In the combination, you must combine any sections Entitled ``History'' in the various original documents, forming one section Entitled ``History''; likewise combine any sections Entitled ``Acknowledgements'', and any sections Entitled ``Dedications''. You must delete all sections Entitled ``Endorsements.'' @item COLLECTIONS OF DOCUMENTS You may make a collection consisting of the Document and other documents released under this License, and replace the individual copies of this License in the various documents with a single copy that is included in the collection, provided that you follow the rules of this License for verbatim copying of each of the documents in all other respects. You may extract a single document from such a collection, and distribute it individually under this License, provided you insert a copy of this License into the extracted document, and follow this License in all other respects regarding verbatim copying of that document. @item AGGREGATION WITH INDEPENDENT WORKS A compilation of the Document or its derivatives with other separate and independent documents or works, in or on a volume of a storage or distribution medium, is called an ``aggregate'' if the copyright resulting from the compilation is not used to limit the legal rights of the compilation's users beyond what the individual works permit. When the Document is included in an aggregate, this License does not apply to the other works in the aggregate which are not themselves derivative works of the Document. If the Cover Text requirement of section 3 is applicable to these copies of the Document, then if the Document is less than one half of the entire aggregate, the Document's Cover Texts may be placed on covers that bracket the Document within the aggregate, or the electronic equivalent of covers if the Document is in electronic form. Otherwise they must appear on printed covers that bracket the whole aggregate. @item TRANSLATION Translation is considered a kind of modification, so you may distribute translations of the Document under the terms of section 4. Replacing Invariant Sections with translations requires special permission from their copyright holders, but you may include translations of some or all Invariant Sections in addition to the original versions of these Invariant Sections. You may include a translation of this License, and all the license notices in the Document, and any Warranty Disclaimers, provided that you also include the original English version of this License and the original versions of those notices and disclaimers. In case of a disagreement between the translation and the original version of this License or a notice or disclaimer, the original version will prevail. If a section in the Document is Entitled ``Acknowledgements'', ``Dedications'', or ``History'', the requirement (section 4) to Preserve its Title (section 1) will typically require changing the actual title. @item TERMINATION You may not copy, modify, sublicense, or distribute the Document except as expressly provided for under this License. Any other attempt to copy, modify, sublicense or distribute the Document is void, and will automatically terminate your rights under this License. However, parties who have received copies, or rights, from you under this License will not have their licenses terminated so long as such parties remain in full compliance. @item FUTURE REVISIONS OF THIS LICENSE The Free Software Foundation may publish new, revised versions of the GNU Free Documentation License from time to time. Such new versions will be similar in spirit to the present version, but may differ in detail to address new problems or concerns. See @uref{http://www.gnu.org/copyleft/}. Each version of the License is given a distinguishing version number. If the Document specifies that a particular numbered version of this License ``or any later version'' applies to it, you have the option of following the terms and conditions either of that specified version or of any later version that has been published (not as a draft) by the Free Software Foundation. If the Document does not specify a version number of this License, you may choose any version ever published (not as a draft) by the Free Software Foundation. @end enumerate @page @section ADDENDUM: How to use this License for your documents To use this License in a document you have written, include a copy of the License in the document and put the following copyright and license notices just after the title page: @smallexample @group Copyright (C) @var{year} @var{your name}. Permission is granted to copy, distribute and/or modify this document under the terms of the GNU Free Documentation License, Version 1.2 or any later version published by the Free Software Foundation; with no Invariant Sections, no Front-Cover Texts, and no Back-Cover Texts. A copy of the license is included in the section entitled ``GNU Free Documentation License''. @end group @end smallexample If you have Invariant Sections, Front-Cover Texts and Back-Cover Texts, replace the ``with...Texts.'' line with this: @smallexample @group with the Invariant Sections being @var{list their titles}, with the Front-Cover Texts being @var{list}, and with the Back-Cover Texts being @var{list}. @end group @end smallexample If you have Invariant Sections without Cover Texts, or some other combination of the three, merge those two alternatives to suit the situation. If your document contains nontrivial examples of program code, we recommend releasing these examples in parallel under your choice of free software license, such as the GNU General Public License, to permit their use in free software. @c Local Variables: @c ispell-local-pdict: "ispell-dict" @c End: ��������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������emms-6.00/doc/gpl.texi������������������������������������������������������������������������������0000664�0001750�0001750�00000104652�13746063641�013042� 0����������������������������������������������������������������������������������������������������ustar �yrk�����������������������������yrk��������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������@node Copying, The GNU FDL, Extending Emms, Top @unnumbered GNU General Public License @center Version 3, 29 June 2007 @c This file is intended to be included in another file. @display Copyright @copyright{} 2007 Free Software Foundation, Inc. @url{http://fsf.org/} Everyone is permitted to copy and distribute verbatim copies of this license document, but changing it is not allowed. @end display @unnumberedsec Preamble The GNU General Public License is a free, copyleft license for software and other kinds of works. The licenses for most software and other practical works are designed to take away your freedom to share and change the works. By contrast, the GNU General Public License is intended to guarantee your freedom to share and change all versions of a program--to make sure it remains free software for all its users. We, the Free Software Foundation, use the GNU General Public License for most of our software; it applies also to any other work released this way by its authors. You can apply it to your programs, too. When we speak of free software, we are referring to freedom, not price. Our General Public Licenses are designed to make sure that you have the freedom to distribute copies of free software (and charge for them if you wish), that you receive source code or can get it if you want it, that you can change the software or use pieces of it in new free programs, and that you know you can do these things. To protect your rights, we need to prevent others from denying you these rights or asking you to surrender the rights. Therefore, you have certain responsibilities if you distribute copies of the software, or if you modify it: responsibilities to respect the freedom of others. For example, if you distribute copies of such a program, whether gratis or for a fee, you must pass on to the recipients the same freedoms that you received. You must make sure that they, too, receive or can get the source code. And you must show them these terms so they know their rights. Developers that use the GNU GPL protect your rights with two steps: (1) assert copyright on the software, and (2) offer you this License giving you legal permission to copy, distribute and/or modify it. For the developers' and authors' protection, the GPL clearly explains that there is no warranty for this free software. For both users' and authors' sake, the GPL requires that modified versions be marked as changed, so that their problems will not be attributed erroneously to authors of previous versions. Some devices are designed to deny users access to install or run modified versions of the software inside them, although the manufacturer can do so. This is fundamentally incompatible with the aim of protecting users' freedom to change the software. The systematic pattern of such abuse occurs in the area of products for individuals to use, which is precisely where it is most unacceptable. Therefore, we have designed this version of the GPL to prohibit the practice for those products. If such problems arise substantially in other domains, we stand ready to extend this provision to those domains in future versions of the GPL, as needed to protect the freedom of users. Finally, every program is threatened constantly by software patents. States should not allow patents to restrict development and use of software on general-purpose computers, but in those that do, we wish to avoid the special danger that patents applied to a free program could make it effectively proprietary. To prevent this, the GPL assures that patents cannot be used to render the program non-free. The precise terms and conditions for copying, distribution and modification follow. @iftex @unnumberedsec TERMS AND CONDITIONS @end iftex @ifinfo @center TERMS AND CONDITIONS @end ifinfo @enumerate 0 @item Definitions. ``This License'' refers to version 3 of the GNU General Public License. ``Copyright'' also means copyright-like laws that apply to other kinds of works, such as semiconductor masks. ``The Program'' refers to any copyrightable work licensed under this License. Each licensee is addressed as ``you''. ``Licensees'' and ``recipients'' may be individuals or organizations. To ``modify'' a work means to copy from or adapt all or part of the work in a fashion requiring copyright permission, other than the making of an exact copy. The resulting work is called a ``modified version'' of the earlier work or a work ``based on'' the earlier work. A ``covered work'' means either the unmodified Program or a work based on the Program. To ``propagate'' a work means to do anything with it that, without permission, would make you directly or secondarily liable for infringement under applicable copyright law, except executing it on a computer or modifying a private copy. Propagation includes copying, distribution (with or without modification), making available to the public, and in some countries other activities as well. To ``convey'' a work means any kind of propagation that enables other parties to make or receive copies. Mere interaction with a user through a computer network, with no transfer of a copy, is not conveying. An interactive user interface displays ``Appropriate Legal Notices'' to the extent that it includes a convenient and prominently visible feature that (1) displays an appropriate copyright notice, and (2) tells the user that there is no warranty for the work (except to the extent that warranties are provided), that licensees may convey the work under this License, and how to view a copy of this License. If the interface presents a list of user commands or options, such as a menu, a prominent item in the list meets this criterion. @item Source Code. The ``source code'' for a work means the preferred form of the work for making modifications to it. ``Object code'' means any non-source form of a work. A ``Standard Interface'' means an interface that either is an official standard defined by a recognized standards body, or, in the case of interfaces specified for a particular programming language, one that is widely used among developers working in that language. The ``System Libraries'' of an executable work include anything, other than the work as a whole, that (a) is included in the normal form of packaging a Major Component, but which is not part of that Major Component, and (b) serves only to enable use of the work with that Major Component, or to implement a Standard Interface for which an implementation is available to the public in source code form. A ``Major Component'', in this context, means a major essential component (kernel, window system, and so on) of the specific operating system (if any) on which the executable work runs, or a compiler used to produce the work, or an object code interpreter used to run it. The ``Corresponding Source'' for a work in object code form means all the source code needed to generate, install, and (for an executable work) run the object code and to modify the work, including scripts to control those activities. However, it does not include the work's System Libraries, or general-purpose tools or generally available free programs which are used unmodified in performing those activities but which are not part of the work. For example, Corresponding Source includes interface definition files associated with source files for the work, and the source code for shared libraries and dynamically linked subprograms that the work is specifically designed to require, such as by intimate data communication or control flow between those subprograms and other parts of the work. The Corresponding Source need not include anything that users can regenerate automatically from other parts of the Corresponding Source. The Corresponding Source for a work in source code form is that same work. @item Basic Permissions. All rights granted under this License are granted for the term of copyright on the Program, and are irrevocable provided the stated conditions are met. This License explicitly affirms your unlimited permission to run the unmodified Program. The output from running a covered work is covered by this License only if the output, given its content, constitutes a covered work. This License acknowledges your rights of fair use or other equivalent, as provided by copyright law. You may make, run and propagate covered works that you do not convey, without conditions so long as your license otherwise remains in force. You may convey covered works to others for the sole purpose of having them make modifications exclusively for you, or provide you with facilities for running those works, provided that you comply with the terms of this License in conveying all material for which you do not control copyright. Those thus making or running the covered works for you must do so exclusively on your behalf, under your direction and control, on terms that prohibit them from making any copies of your copyrighted material outside their relationship with you. Conveying under any other circumstances is permitted solely under the conditions stated below. Sublicensing is not allowed; section 10 makes it unnecessary. @item Protecting Users' Legal Rights From Anti-Circumvention Law. No covered work shall be deemed part of an effective technological measure under any applicable law fulfilling obligations under article 11 of the WIPO copyright treaty adopted on 20 December 1996, or similar laws prohibiting or restricting circumvention of such measures. When you convey a covered work, you waive any legal power to forbid circumvention of technological measures to the extent such circumvention is effected by exercising rights under this License with respect to the covered work, and you disclaim any intention to limit operation or modification of the work as a means of enforcing, against the work's users, your or third parties' legal rights to forbid circumvention of technological measures. @item Conveying Verbatim Copies. You may convey verbatim copies of the Program's source code as you receive it, in any medium, provided that you conspicuously and appropriately publish on each copy an appropriate copyright notice; keep intact all notices stating that this License and any non-permissive terms added in accord with section 7 apply to the code; keep intact all notices of the absence of any warranty; and give all recipients a copy of this License along with the Program. You may charge any price or no price for each copy that you convey, and you may offer support or warranty protection for a fee. @item Conveying Modified Source Versions. You may convey a work based on the Program, or the modifications to produce it from the Program, in the form of source code under the terms of section 4, provided that you also meet all of these conditions: @enumerate a @item The work must carry prominent notices stating that you modified it, and giving a relevant date. @item The work must carry prominent notices stating that it is released under this License and any conditions added under section 7. This requirement modifies the requirement in section 4 to ``keep intact all notices''. @item You must license the entire work, as a whole, under this License to anyone who comes into possession of a copy. This License will therefore apply, along with any applicable section 7 additional terms, to the whole of the work, and all its parts, regardless of how they are packaged. This License gives no permission to license the work in any other way, but it does not invalidate such permission if you have separately received it. @item If the work has interactive user interfaces, each must display Appropriate Legal Notices; however, if the Program has interactive interfaces that do not display Appropriate Legal Notices, your work need not make them do so. @end enumerate A compilation of a covered work with other separate and independent works, which are not by their nature extensions of the covered work, and which are not combined with it such as to form a larger program, in or on a volume of a storage or distribution medium, is called an ``aggregate'' if the compilation and its resulting copyright are not used to limit the access or legal rights of the compilation's users beyond what the individual works permit. Inclusion of a covered work in an aggregate does not cause this License to apply to the other parts of the aggregate. @item Conveying Non-Source Forms. You may convey a covered work in object code form under the terms of sections 4 and 5, provided that you also convey the machine-readable Corresponding Source under the terms of this License, in one of these ways: @enumerate a @item Convey the object code in, or embodied in, a physical product (including a physical distribution medium), accompanied by the Corresponding Source fixed on a durable physical medium customarily used for software interchange. @item Convey the object code in, or embodied in, a physical product (including a physical distribution medium), accompanied by a written offer, valid for at least three years and valid for as long as you offer spare parts or customer support for that product model, to give anyone who possesses the object code either (1) a copy of the Corresponding Source for all the software in the product that is covered by this License, on a durable physical medium customarily used for software interchange, for a price no more than your reasonable cost of physically performing this conveying of source, or (2) access to copy the Corresponding Source from a network server at no charge. @item Convey individual copies of the object code with a copy of the written offer to provide the Corresponding Source. This alternative is allowed only occasionally and noncommercially, and only if you received the object code with such an offer, in accord with subsection 6b. @item Convey the object code by offering access from a designated place (gratis or for a charge), and offer equivalent access to the Corresponding Source in the same way through the same place at no further charge. You need not require recipients to copy the Corresponding Source along with the object code. If the place to copy the object code is a network server, the Corresponding Source may be on a different server (operated by you or a third party) that supports equivalent copying facilities, provided you maintain clear directions next to the object code saying where to find the Corresponding Source. Regardless of what server hosts the Corresponding Source, you remain obligated to ensure that it is available for as long as needed to satisfy these requirements. @item Convey the object code using peer-to-peer transmission, provided you inform other peers where the object code and Corresponding Source of the work are being offered to the general public at no charge under subsection 6d. @end enumerate A separable portion of the object code, whose source code is excluded from the Corresponding Source as a System Library, need not be included in conveying the object code work. A ``User Product'' is either (1) a ``consumer product'', which means any tangible personal property which is normally used for personal, family, or household purposes, or (2) anything designed or sold for incorporation into a dwelling. In determining whether a product is a consumer product, doubtful cases shall be resolved in favor of coverage. For a particular product received by a particular user, ``normally used'' refers to a typical or common use of that class of product, regardless of the status of the particular user or of the way in which the particular user actually uses, or expects or is expected to use, the product. A product is a consumer product regardless of whether the product has substantial commercial, industrial or non-consumer uses, unless such uses represent the only significant mode of use of the product. ``Installation Information'' for a User Product means any methods, procedures, authorization keys, or other information required to install and execute modified versions of a covered work in that User Product from a modified version of its Corresponding Source. The information must suffice to ensure that the continued functioning of the modified object code is in no case prevented or interfered with solely because modification has been made. If you convey an object code work under this section in, or with, or specifically for use in, a User Product, and the conveying occurs as part of a transaction in which the right of possession and use of the User Product is transferred to the recipient in perpetuity or for a fixed term (regardless of how the transaction is characterized), the Corresponding Source conveyed under this section must be accompanied by the Installation Information. But this requirement does not apply if neither you nor any third party retains the ability to install modified object code on the User Product (for example, the work has been installed in ROM). The requirement to provide Installation Information does not include a requirement to continue to provide support service, warranty, or updates for a work that has been modified or installed by the recipient, or for the User Product in which it has been modified or installed. Access to a network may be denied when the modification itself materially and adversely affects the operation of the network or violates the rules and protocols for communication across the network. Corresponding Source conveyed, and Installation Information provided, in accord with this section must be in a format that is publicly documented (and with an implementation available to the public in source code form), and must require no special password or key for unpacking, reading or copying. @item Additional Terms. ``Additional permissions'' are terms that supplement the terms of this License by making exceptions from one or more of its conditions. Additional permissions that are applicable to the entire Program shall be treated as though they were included in this License, to the extent that they are valid under applicable law. If additional permissions apply only to part of the Program, that part may be used separately under those permissions, but the entire Program remains governed by this License without regard to the additional permissions. When you convey a copy of a covered work, you may at your option remove any additional permissions from that copy, or from any part of it. (Additional permissions may be written to require their own removal in certain cases when you modify the work.) You may place additional permissions on material, added by you to a covered work, for which you have or can give appropriate copyright permission. Notwithstanding any other provision of this License, for material you add to a covered work, you may (if authorized by the copyright holders of that material) supplement the terms of this License with terms: @enumerate a @item Disclaiming warranty or limiting liability differently from the terms of sections 15 and 16 of this License; or @item Requiring preservation of specified reasonable legal notices or author attributions in that material or in the Appropriate Legal Notices displayed by works containing it; or @item Prohibiting misrepresentation of the origin of that material, or requiring that modified versions of such material be marked in reasonable ways as different from the original version; or @item Limiting the use for publicity purposes of names of licensors or authors of the material; or @item Declining to grant rights under trademark law for use of some trade names, trademarks, or service marks; or @item Requiring indemnification of licensors and authors of that material by anyone who conveys the material (or modified versions of it) with contractual assumptions of liability to the recipient, for any liability that these contractual assumptions directly impose on those licensors and authors. @end enumerate All other non-permissive additional terms are considered ``further restrictions'' within the meaning of section 10. If the Program as you received it, or any part of it, contains a notice stating that it is governed by this License along with a term that is a further restriction, you may remove that term. If a license document contains a further restriction but permits relicensing or conveying under this License, you may add to a covered work material governed by the terms of that license document, provided that the further restriction does not survive such relicensing or conveying. If you add terms to a covered work in accord with this section, you must place, in the relevant source files, a statement of the additional terms that apply to those files, or a notice indicating where to find the applicable terms. Additional terms, permissive or non-permissive, may be stated in the form of a separately written license, or stated as exceptions; the above requirements apply either way. @item Termination. You may not propagate or modify a covered work except as expressly provided under this License. Any attempt otherwise to propagate or modify it is void, and will automatically terminate your rights under this License (including any patent licenses granted under the third paragraph of section 11). However, if you cease all violation of this License, then your license from a particular copyright holder is reinstated (a) provisionally, unless and until the copyright holder explicitly and finally terminates your license, and (b) permanently, if the copyright holder fails to notify you of the violation by some reasonable means prior to 60 days after the cessation. Moreover, your license from a particular copyright holder is reinstated permanently if the copyright holder notifies you of the violation by some reasonable means, this is the first time you have received notice of violation of this License (for any work) from that copyright holder, and you cure the violation prior to 30 days after your receipt of the notice. Termination of your rights under this section does not terminate the licenses of parties who have received copies or rights from you under this License. If your rights have been terminated and not permanently reinstated, you do not qualify to receive new licenses for the same material under section 10. @item Acceptance Not Required for Having Copies. You are not required to accept this License in order to receive or run a copy of the Program. Ancillary propagation of a covered work occurring solely as a consequence of using peer-to-peer transmission to receive a copy likewise does not require acceptance. However, nothing other than this License grants you permission to propagate or modify any covered work. These actions infringe copyright if you do not accept this License. Therefore, by modifying or propagating a covered work, you indicate your acceptance of this License to do so. @item Automatic Licensing of Downstream Recipients. Each time you convey a covered work, the recipient automatically receives a license from the original licensors, to run, modify and propagate that work, subject to this License. You are not responsible for enforcing compliance by third parties with this License. An ``entity transaction'' is a transaction transferring control of an organization, or substantially all assets of one, or subdividing an organization, or merging organizations. If propagation of a covered work results from an entity transaction, each party to that transaction who receives a copy of the work also receives whatever licenses to the work the party's predecessor in interest had or could give under the previous paragraph, plus a right to possession of the Corresponding Source of the work from the predecessor in interest, if the predecessor has it or can get it with reasonable efforts. You may not impose any further restrictions on the exercise of the rights granted or affirmed under this License. For example, you may not impose a license fee, royalty, or other charge for exercise of rights granted under this License, and you may not initiate litigation (including a cross-claim or counterclaim in a lawsuit) alleging that any patent claim is infringed by making, using, selling, offering for sale, or importing the Program or any portion of it. @item Patents. A ``contributor'' is a copyright holder who authorizes use under this License of the Program or a work on which the Program is based. The work thus licensed is called the contributor's ``contributor version''. A contributor's ``essential patent claims'' are all patent claims owned or controlled by the contributor, whether already acquired or hereafter acquired, that would be infringed by some manner, permitted by this License, of making, using, or selling its contributor version, but do not include claims that would be infringed only as a consequence of further modification of the contributor version. For purposes of this definition, ``control'' includes the right to grant patent sublicenses in a manner consistent with the requirements of this License. Each contributor grants you a non-exclusive, worldwide, royalty-free patent license under the contributor's essential patent claims, to make, use, sell, offer for sale, import and otherwise run, modify and propagate the contents of its contributor version. In the following three paragraphs, a ``patent license'' is any express agreement or commitment, however denominated, not to enforce a patent (such as an express permission to practice a patent or covenant not to sue for patent infringement). To ``grant'' such a patent license to a party means to make such an agreement or commitment not to enforce a patent against the party. If you convey a covered work, knowingly relying on a patent license, and the Corresponding Source of the work is not available for anyone to copy, free of charge and under the terms of this License, through a publicly available network server or other readily accessible means, then you must either (1) cause the Corresponding Source to be so available, or (2) arrange to deprive yourself of the benefit of the patent license for this particular work, or (3) arrange, in a manner consistent with the requirements of this License, to extend the patent license to downstream recipients. ``Knowingly relying'' means you have actual knowledge that, but for the patent license, your conveying the covered work in a country, or your recipient's use of the covered work in a country, would infringe one or more identifiable patents in that country that you have reason to believe are valid. If, pursuant to or in connection with a single transaction or arrangement, you convey, or propagate by procuring conveyance of, a covered work, and grant a patent license to some of the parties receiving the covered work authorizing them to use, propagate, modify or convey a specific copy of the covered work, then the patent license you grant is automatically extended to all recipients of the covered work and works based on it. A patent license is ``discriminatory'' if it does not include within the scope of its coverage, prohibits the exercise of, or is conditioned on the non-exercise of one or more of the rights that are specifically granted under this License. You may not convey a covered work if you are a party to an arrangement with a third party that is in the business of distributing software, under which you make payment to the third party based on the extent of your activity of conveying the work, and under which the third party grants, to any of the parties who would receive the covered work from you, a discriminatory patent license (a) in connection with copies of the covered work conveyed by you (or copies made from those copies), or (b) primarily for and in connection with specific products or compilations that contain the covered work, unless you entered into that arrangement, or that patent license was granted, prior to 28 March 2007. Nothing in this License shall be construed as excluding or limiting any implied license or other defenses to infringement that may otherwise be available to you under applicable patent law. @item No Surrender of Others' Freedom. If conditions are imposed on you (whether by court order, agreement or otherwise) that contradict the conditions of this License, they do not excuse you from the conditions of this License. If you cannot convey a covered work so as to satisfy simultaneously your obligations under this License and any other pertinent obligations, then as a consequence you may not convey it at all. For example, if you agree to terms that obligate you to collect a royalty for further conveying from those to whom you convey the Program, the only way you could satisfy both those terms and this License would be to refrain entirely from conveying the Program. @item Use with the GNU Affero General Public License. Notwithstanding any other provision of this License, you have permission to link or combine any covered work with a work licensed under version 3 of the GNU Affero General Public License into a single combined work, and to convey the resulting work. The terms of this License will continue to apply to the part which is the covered work, but the special requirements of the GNU Affero General Public License, section 13, concerning interaction through a network will apply to the combination as such. @item Revised Versions of this License. The Free Software Foundation may publish revised and/or new versions of the GNU General Public License from time to time. Such new versions will be similar in spirit to the present version, but may differ in detail to address new problems or concerns. Each version is given a distinguishing version number. If the Program specifies that a certain numbered version of the GNU General Public License ``or any later version'' applies to it, you have the option of following the terms and conditions either of that numbered version or of any later version published by the Free Software Foundation. If the Program does not specify a version number of the GNU General Public License, you may choose any version ever published by the Free Software Foundation. If the Program specifies that a proxy can decide which future versions of the GNU General Public License can be used, that proxy's public statement of acceptance of a version permanently authorizes you to choose that version for the Program. Later license versions may give you additional or different permissions. However, no additional obligations are imposed on any author or copyright holder as a result of your choosing to follow a later version. @item Disclaimer of Warranty. THERE IS NO WARRANTY FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES PROVIDE THE PROGRAM ``AS IS'' WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING, REPAIR OR CORRECTION. @item Limitation of Liability. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MODIFIES AND/OR CONVEYS THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES. @item Interpretation of Sections 15 and 16. If the disclaimer of warranty and limitation of liability provided above cannot be given local legal effect according to their terms, reviewing courts shall apply local law that most closely approximates an absolute waiver of all civil liability in connection with the Program, unless a warranty or assumption of liability accompanies a copy of the Program in return for a fee. @end enumerate @iftex @heading END OF TERMS AND CONDITIONS @end iftex @ifinfo @center END OF TERMS AND CONDITIONS @end ifinfo @unnumberedsec How to Apply These Terms to Your New Programs If you develop a new program, and you want it to be of the greatest possible use to the public, the best way to achieve this is to make it free software which everyone can redistribute and change under these terms. To do so, attach the following notices to the program. It is safest to attach them to the start of each source file to most effectively state the exclusion of warranty; and each file should have at least the ``copyright'' line and a pointer to where the full notice is found. @smallexample @var{one line to give the program's name and a brief idea of what it does.} Copyright (C) @var{year} @var{name of author} This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program. If not, see @url{http://www.gnu.org/licenses/}. @end smallexample Also add information on how to contact you by electronic and paper mail. If the program does terminal interaction, make it output a short notice like this when it starts in an interactive mode: @smallexample @var{program} Copyright (C) @var{year} @var{name of author} This program comes with ABSOLUTELY NO WARRANTY; for details type @samp{show w}. This is free software, and you are welcome to redistribute it under certain conditions; type @samp{show c} for details. @end smallexample The hypothetical commands @samp{show w} and @samp{show c} should show the appropriate parts of the General Public License. Of course, your program's commands might be different; for a GUI interface, you would use an ``about box''. You should also get your employer (if you work as a programmer) or school, if any, to sign a ``copyright disclaimer'' for the program, if necessary. For more information on this, and how to apply and follow the GNU GPL, see @url{http://www.gnu.org/licenses/}. The GNU General Public License does not permit incorporating your program into proprietary programs. If your program is a subroutine library, you may consider it more useful to permit linking proprietary applications with the library. If this is what you want to do, use the GNU Lesser General Public License instead of this License. But first, please read @url{http://www.gnu.org/philosophy/why-not-lgpl.html}. ��������������������������������������������������������������������������������������emms-6.00/emms-auto.in������������������������������������������������������������������������������0000664�0001750�0001750�00000000770�13746063641�013053� 0����������������������������������������������������������������������������������������������������ustar �yrk�����������������������������yrk��������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������;;; -*-emacs-lisp-*- (defvar generated-autoload-file) (defvar command-line-args-left) (defun emms-generate-autoloads () (interactive) (require 'autoload) (setq generated-autoload-file (car command-line-args-left)) (setq command-line-args-left (cdr command-line-args-left)) (batch-update-autoloads)) (add-to-list 'load-path (directory-file-name (or (file-name-directory load-file-name) (car load-path)))) (provide 'emms-auto) ;;; Generated autoloads follow (made by autoload.el). ��������emms-6.00/emms-bookmarks.el�������������������������������������������������������������������������0000664�0001750�0001750�00000012416�13746063641�014065� 0����������������������������������������������������������������������������������������������������ustar �yrk�����������������������������yrk��������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������;;; emms-bookmarks.el --- Bookmarks for Emms. ;; Copyright (C) 2006, 2007, 2008, 2009 Free Software Foundation, Inc. ;; Author: Yoni Rabkin <yrk@gnu.org> ;; Keywords: emms, bookmark ;; 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, 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: ;; ;; You can use this to add ``temporal bookmarks'' (term by Lucas ;; Bonnet) to your media files. The interesting functions here are ;; `emms-bookmarks-next', `emms-bookmarks-prev', `emms-bookmarks-add' ;; (which pauses the player while you describe the bookmark) and ;; `emms-bookmarks-clear'. All of which do exactly what you think ;; they do. ;;; Code: ;; dependencies (require 'emms) (require 'emms-playing-time) (defvar emms-bookmarks-prev-overshoot 5 "Time in seconds for skipping a previous bookmark.") (defun emms-bookmarks-reset (track) "Remove all the bookmarks from TRACK." (emms-track-set track 'bookmarks nil)) (defun emms-bookmarks-straight-insertion-sort (item l acc) "Insert ITEM into the already sorted L, ACC should be nil." (if (null l) (append acc (list item)) (cond ((< (cdr item) (cdr (car l))) (append acc (list item (car l)) (cdr l))) (t (emms-bookmarks-straight-insertion-sort item (cdr l) (append acc (list (car l)))))))) (defun emms-bookmarks-get (track) "Return the bookmark property from TRACK." (emms-track-get track 'bookmarks)) (defun emms-bookmarks-set (track desc time) "Set bookmark property for TRACK, text DESC at TIME seconds." (let ((old-bookmarks (emms-track-get track 'bookmarks)) (new-bookmarks nil)) (setq new-bookmarks (emms-bookmarks-straight-insertion-sort (cons desc time) old-bookmarks nil)) (emms-track-set track 'bookmarks new-bookmarks))) (defun emms-bookmarks-set-current (desc) "Set bookmark property for the current track with text DESC." (emms-bookmarks-set (emms-playlist-current-selected-track) desc emms-playing-time)) (defun emms-bookmarks-search (time track test) "Return a bookmark based on heuristics. TIME should be a reference point in seconds. TRACK should be an Emms track. TEST should be a numerical comparator predicate." (let ((s (append (list (cons "time" time)) (copy-sequence (emms-bookmarks-get track))))) (sort s #'(lambda (a b) (funcall test (cdr a) (cdr b)))) (while (not (= time (cdar s))) (setq s (cdr s))) (when (cdr s) (car (cdr s))))) (defun emms-bookmarks-next-1 (time track) "Return the bookmark after TIME for TRACK, otherwise return nil." (emms-bookmarks-search time track #'<)) (defun emms-bookmarks-prev-1 (time track) "Return the bookmark before TIME for TRACK, otherwise return nil." (emms-bookmarks-search (- time emms-bookmarks-prev-overshoot) track #'>)) (defun emms-bookmarks-goto (search-f track failure-message) "Seek the player to a bookmark. SEARCH-F should be a function which returns a bookmark. TRACK should be an Emms track. FAILURE-MESSAGE should be a string." ;; note that when emms is paused then `emms-player-playing-p' => t (when (not emms-player-playing-p) (emms-start)) (let ((m (funcall search-f emms-playing-time track))) (if m (progn (emms-player-seek-to (cdr m)) (message "%s" (car m))) (message "%s" failure-message)))) ;; entry points (defun emms-bookmarks-next () "Seek to the next bookmark in the current track." (interactive) (emms-bookmarks-goto #'emms-bookmarks-next-1 (emms-playlist-current-selected-track) "No next bookmark")) (defun emms-bookmarks-prev () "Seek to the previous bookmark in the current track." (interactive) (emms-bookmarks-goto #'emms-bookmarks-prev-1 (emms-playlist-current-selected-track) "No previous bookmark")) (defmacro emms-bookmarks-with-paused-player (&rest body) "Eval BODY with player paused." `(progn (when (not emms-player-paused-p) (emms-pause)) ,@body (when emms-player-paused-p (emms-pause)))) ;; can't use `interactive' to promt the user here because we want to ;; pause the player before the prompt appears. (defun emms-bookmarks-add () "Add a new bookmark to the current track. This function pauses the player while prompting the user for a description of the bookmark. The function resumes the player after the prompt." (interactive) (emms-bookmarks-with-paused-player (let ((desc (read-string "Description: "))) (if (emms-playlist-current-selected-track) (emms-bookmarks-set-current desc) (error "No current track to bookmark"))))) (defun emms-bookmarks-clear () "Remove all the bookmarks from the current track." (interactive) (let ((this (emms-playlist-current-selected-track))) (when this (emms-bookmarks-reset this)))) (provide 'emms-bookmarks) ;;; emms-bookmarks.el ends here ��������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������emms-6.00/emms-browser.el���������������������������������������������������������������������������0000664�0001750�0001750�00000243603�13746063641�013564� 0����������������������������������������������������������������������������������������������������ustar �yrk�����������������������������yrk��������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������;;; emms-browser.el --- a track browser supporting covers and filtering ;; Copyright (C) 2006, 2007, 2008, 2009 Free Software Foundation, Inc. ;; Author: Damien Elmes <emacs@repose.cx> ;; Keywords: emms, mp3, mpeg, multimedia ;; 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, 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; see the file COPYING. If not, write to the ;; Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, ;; Boston, MA 02110-1301, USA. ;;; Commentary: ;; This code allows you to browse the metadata cache and add tracks to ;; your playlist. To be properly useful, you should M-x ;; emms-add-directory-tree to all the files you own at least once so ;; that the cache is fully populated. ;; Usage ;; ------------------------------------------------------------------- ;; To use, run (emms-all) and then bind `emms-smart-browse' to a key, ;; like: ;; (global-set-key (kbd "<f2>") 'emms-smart-browse) ;; The 'smart browsing' code attempts to link the browser and playlist ;; windows together, so that closing one will close both. Activating ;; it will toggle between three states: ;; a) both windows displayed, with the browser focused ;; b) focus switched to the playlist window ;; c) the extra window closed, and both buffers buried ;; If you just want access to the browser, try M-x ;; emms-browse-by-TYPE, where TYPE is one of artist, album, composer, ;; genre or year. These commands can also be used while smart browsing to ;; change the browsing category. ;; If you don't want to activate the code with (emms-devel), you can ;; activate it manually with: ;; (require 'emms-browser) ;; Key bindings ;; ------------------------------------------------------------------- ;; 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 ;; 3 emms-browser-expand-to-level-3 ;; 4 emms-browser-expand-to-level-4 ;; < emms-browser-previous-filter ;; > emms-browser-next-filter ;; ? describe-mode ;; C emms-browser-clear-playlist ;; E emms-browser-expand-all ;; d emms-browser-view-in-dired ;; D emms-browser-delete-files ;; q emms-browser-bury-buffer ;; r emms-browser-goto-random ;; n next-line ;; p previous-line ;; C-/ emms-playlist-mode-undo ;; <C-return> emms-browser-add-tracks-and-play ;; <backtab> emms-browser-prev-non-track ;; <tab> emms-browser-next-non-track ;; s A emms-browser-search-by-album ;; s a emms-browser-search-by-artist ;; s c emms-browser-search-by-composer ;; s s emms-browser-search-by-names ;; s t emms-browser-search-by-title ;; s p emms-browser-search-by-performer ;; b 1 emms-browse-by-artist ;; b 2 emms-browse-by-album ;; b 3 emms-browse-by-genre ;; b 4 emms-browse-by-year ;; b 5 emms-browse-by-composer ;; b 6 emms-browse-by-performer ;; W a w emms-browser-lookup-album-on-wikipedia ;; W A w emms-browser-lookup-artist-on-wikipedia ;; W C w emms-browser-lookup-composer-on-wikipedia ;; W P w emms-browser-lookup-performer-on-wikipedia ;; Displaying covers ;; ------------------------------------------------------------------- ;; The browser will attempt to display cover images if they're ;; available. By default it looks for images cover_small.jpg, ;; cover_med.jpg, etc. Customize emms-browser-covers to use your own ;; covers. Note that you'll probably want to resize your existing ;; covers to particular sizes. Suggested sizes are 100x100 for small, ;; and 200x200 for medium. ;; Also emacs by default will jump around a lot when scrolling a ;; buffer with images. Set the following variables to prevent that: ;; scroll-up-aggressively 0.0 ;; scroll-down-aggressively 0.0 ;; To show a 'no cover' image for albums which don't have a cover, add ;; the following code to your .emacs: ;; (setq emms-browser-default-covers ;; (list "/path/to/cover_small.jpg" nil nil) ;; (the medium and large images can be set too, if you want) ;; You can download an example 'no cover' image from: ;; http://repose.cx/cover_small.jpg ;; Filtering tracks ;; ------------------------------------------------------------------- ;; If you want to display a subset of your collection (such as a ;; directory of 80s music, only avi files, etc), then you can make ;; some filters using code like this: ;; ;; show everything ;; (emms-browser-make-filter "all" 'ignore) ;; ;; Set "all" as the default filter ;; (emms-browser-set-filter (assoc "all" emms-browser-filters)) ;; ;; show all files (no streamlists, etc) ;; (emms-browser-make-filter ;; "all-files" (emms-browser-filter-only-type 'file)) ;; ;; show only tracks in one folder ;; (emms-browser-make-filter ;; "80s" (emms-browser-filter-only-dir "~/Mp3s/80s")) ;; ;; show all tracks played in the last month ;; (emms-browser-make-filter ;; "last-month" (emms-browser-filter-only-recent 30)) ;; After executing the above commands, you can use M-x ;; emms-browser-show-all, emms-browser-show-80s, etc to toggle ;; between different collections. Alternatively you can use '<' and ;; '>' to cycle through the available filters. ;; The second argument to make-filter is a function which returns t if ;; a single track should be filtered. You can write your own filter ;; functions to check the type of a file, etc. ;; Some more examples: ;; ;; show only tracks not played in the last year ;; (emms-browser-make-filter "not-played" ;; (lambda (track) ;; (not (funcall (emms-browser-filter-only-recent 365) track)))) ;; ;; show all files that are not in the pending directory ;; (emms-browser-make-filter ;; "all" ;; (lambda (track) ;; (or ;; (funcall (emms-browser-filter-only-type 'file) track) ;; (not (funcall ;; (emms-browser-filter-only-dir "~/Media/pending") track))))) ;; Changing tree structure ;; ------------------------------------------------------------------- ;; You can change the way the tree is displayed by modifying ;; `emms-browser-next-mapping-type'. The following code displays ;; artist->track instead of artist->album->track when you switch to ;; the 'singles' filter. ;; (defadvice emms-browser-next-mapping-type ;; (after no-album (current-mapping)) ;; (when (eq ad-return-value 'info-album) ;; (setq ad-return-value 'info-title))) ;; (defun toggle-album-display () ;; (if (string= emms-browser-current-filter-name "singles") ;; (ad-activate 'emms-browser-next-mapping-type) ;; (ad-deactivate 'emms-browser-next-mapping-type))) ;; (add-hook 'emms-browser-filter-changed-hook 'toggle-album-display) ;; Changing display format ;; ------------------------------------------------------------------- ;; Format strings govern the way items are displayed in the browser ;; and playlist. You can customize these if you wish. ;; `emms-browser-default-format' controls the format to use when no ;; other format has been explicitly defined. By default, only track and ;; albums deviate from the default. ;; To customise the format of a particular type, find the name of the ;; field you want to use (eg `info-artist', `info-title', etc), and ;; insert that into emms-browser-<type>-format or ;; emms-browser-playlist-<type>-format. For example, if you wanted to ;; remove track numbers from tracks in both the browser and playlist, ;; you could do: ;; (defvar emms-browser-info-title-format "%i%n") ;; (defvar emms-browser-playlist-info-title-format ;; emms-browser-info-title-format) ;; The format specifiers available include: ;; %i indent relative to the current level ;; %n the value of the item - eg -info-artist might be "pink floyd" ;; %y the album year ;; %A the album name ;; %a the artist name of the track ;; %C the composer name of the track ;; %p the performer name of the track ;; %t the title of the track ;; %T the track number ;; %cS a small album cover ;; %cM a medium album cover ;; %cL a big album cover ;; Note that if you use track-related items like %t, it will take the ;; data from the first track. ;; Changing display faces ;; ------------------------------------------------------------------- ;; The faces used to display the various fields are also customizable. ;; They are in the format emms-browser-<type>-face, where type is one ;; of "year/genre", "artist", "composer", "performer", "album" or ;; "track". Note that faces lack the initial "info-" part. For example, ;; to change the artist face, type ;; M-x customize-face emms-browser-artist-face. ;; Deleting files ;; ------------------------------------------------------------------- ;; You can use the browser to delete tracks from your hard disk. ;; Because this is dangerous, it is disabled by default. ;; The following code will delete covers at the same time, and remove ;; parent directories if they're now empty. ;; (defun de-kill-covers-and-parents (dir tracks) ;; (when (> (length tracks) 1) ;; ;; if we're not deleting an individual file, delete covers too ;; (dolist (cover '("cover.jpg" ;; "cover_med.jpg" ;; "cover_small.jpg" ;; "folder.jpg")) ;; (condition-case nil ;; (delete-file (concat dir cover)) ;; (error nil))) ;; ;; try and delete empty parents - we actually do the work of the ;; ;; calling function here, too ;; (let (failed) ;; (while (and (not (string= dir "/")) ;; (not failed)) ;; (condition-case nil ;; (delete-directory dir) ;; (error (setq failed t))) ;; (setq dir (file-name-directory (directory-file-name dir))))))) ;; (add-hook 'emms-browser-delete-files-hook 'de-kill-covers-and-parents) ;;; Code: (require 'cl-lib) (require 'emms) (require 'emms-cache) (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-" :group 'multimedia :group 'applications) (defcustom emms-browser-default-browse-type 'info-artist "*The default browsing mode." :group 'emms-browser :type 'function) (defcustom emms-browser-make-name-function 'emms-browser-make-name-standard "*A function to make names for entries and subentries. Overriding this function allows you to customise how various elements are displayed. It is called with two arguments - track and type." :group 'emms-browser :type 'function) (defcustom emms-browser-get-track-field-function '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, `emms-browser-get-track-field-use-directory-name' uses the directory name to determine the artist. This means that soundtracks, compilations and so on don't populate the artist view with lots of 1-track elements." :group 'emms-browser :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") "*Control how cover images are found. Can be either a list of small, medium and large images (large currently not used), a function which takes a directory and one of the symbols `small', `medium' or `large', and should return a path to the cover, or nil to turn off cover loading." :group 'emms-browser :type '(choice list function boolean)) (defcustom emms-browser-covers-file-extensions '("jpg" "jpeg" "png" "gif" "bmp") "*File extensions accepted for `emms-browser-covers'. Should be a list of extensions as strings. Should be set before emms-browser is required." :group 'emms-browser :type '(repeat (string :tag "Extension"))) (defconst emms-browser--covers-filename nil "*List of potential cover art names.") (defcustom emms-browser-default-covers nil "*A list of default images to use if a cover isn't found." :group 'emms-browser :type 'list) (defcustom emms-browser-comparison-test (if (fboundp 'define-hash-table-test) 'case-fold 'equal) "*A method for comparing entries in the cache. The default is to compare case-insensitively." :group 'emms-browser :type 'symbol) (defcustom emms-browser-track-sort-function 'emms-sort-natural-order-less-p "*How to sort tracks in the browser. Ues nil for no sorting." :group 'emms-browser :type 'function) (defcustom emms-browser-alpha-sort-function (if (functionp 'string-collate-lessp) 'string-collate-lessp 'string<) "*How to sort artists/albums/etc. in the browser. Use nil for no sorting." :group 'emms-browser :type 'function) (defcustom emms-browser-album-sort-function 'emms-browser-sort-by-year-or-name "*How to sort artists/albums/etc. in the browser. Use nil for no sorting." :group 'emms-browser :type 'function) (defcustom emms-browser-show-display-hook nil "*Hooks to run when starting or switching to a browser buffer." :group 'emms-browser :type 'hook) (defcustom emms-browser-hide-display-hook nil "*Hooks to run when burying or removing a browser buffer." :group 'emms-browser :type 'hook) (defcustom emms-browser-tracks-added-hook nil "*Hooks to run when tracks are added to the playlist." :group 'emms-browser :type 'hook) (defcustom emms-browser-filter-tracks-hook nil "*Given a track, return t if the track should be ignored." :group 'emms-browser :type 'hook) (defcustom emms-browser-filter-changed-hook nil "*Hook run after the filter has changed." :group 'emms-browser :type 'hook) (defcustom emms-browser-delete-files-hook nil "*Hook run after files have been deleted. This hook can be used to clean up extra files, such as album covers. Called once for each directory." :group 'emms-browser :type 'hook) (defvar emms-browser-buffer nil "The current browser buffer, if any.") (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) (defvar emms-browser-top-level-type nil "The current mapping type, eg. 'info-artist.") (make-variable-buffer-local 'emms-browser-top-level-type) (defvar emms-browser-current-indent nil "Used to override the current indent, for the playlist, etc.") (defvar emms-browser-current-filter-name nil "The name of the current filter in place, if any.") (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) (define-key map (kbd "r") 'emms-browser-goto-random) (define-key map (kbd "n") 'next-line) (define-key map (kbd "p") 'previous-line) (define-key map (kbd "C") 'emms-browser-clear-playlist) (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 "<C-return>") 'emms-browser-add-tracks-and-play) (define-key map (kbd "C-j") 'emms-browser-add-tracks-and-play) (define-key map (kbd "<tab>") 'emms-browser-next-non-track) (define-key map (kbd "<backtab>") 'emms-browser-prev-non-track) (define-key map (kbd "d") 'emms-browser-view-in-dired) (define-key map (kbd "D") 'emms-browser-delete-files) (define-key map (kbd "E") 'emms-browser-expand-all) (define-key map (kbd "1") 'emms-browser-collapse-all) (define-key map (kbd "2") 'emms-browser-expand-to-level-2) (define-key map (kbd "3") 'emms-browser-expand-to-level-3) (define-key map (kbd "4") 'emms-browser-expand-to-level-4) (define-key map (kbd "b 1") 'emms-browse-by-artist) (define-key map (kbd "b 2") 'emms-browse-by-album) (define-key map (kbd "b 3") 'emms-browse-by-genre) (define-key map (kbd "b 4") 'emms-browse-by-year) (define-key map (kbd "b 5") 'emms-browse-by-composer) (define-key map (kbd "b 6") 'emms-browse-by-performer) (define-key map (kbd "s a") 'emms-browser-search-by-artist) (define-key map (kbd "s c") 'emms-browser-search-by-composer) (define-key map (kbd "s p") 'emms-browser-search-by-performer) (define-key map (kbd "s A") 'emms-browser-search-by-album) (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 C w") 'emms-browser-lookup-composer-on-wikipedia) (define-key map (kbd "W P w") 'emms-browser-lookup-performer-on-wikipedia) (define-key map (kbd "W a w") 'emms-browser-lookup-album-on-wikipedia) (define-key map (kbd ">") 'emms-browser-next-filter) (define-key map (kbd "<") 'emms-browser-previous-filter) (define-key map (kbd "+") 'emms-volume-raise) (define-key map (kbd "-") 'emms-volume-lower) map) "Keymap for `emms-browser-mode'.") (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) map) "Keymap for `emms-browser-mode'.") ;; -------------------------------------------------- ;; Compatability functions ;; -------------------------------------------------- (eval-and-compile (if (fboundp 'with-selected-window) (defalias 'emms-browser-with-selected-window 'with-selected-window) (defmacro emms-browser-with-selected-window (window &rest body) ;; this emulates the behavior introduced earlier, though it ;; might be best to do something with `window' `(save-selected-window ,body))) (put 'emms-browser-with-selected-window 'lisp-indent-function 1) (put 'emms-browser-with-selected-window 'edebug-form-spec '(form body)) (if (fboundp 'run-mode-hooks) (defalias 'emms-browser-run-mode-hooks 'run-mode-hooks) (defalias 'emms-browser-run-mode-hooks 'run-hooks))) ;; -------------------------------------------------- ;; General mode setup ;; -------------------------------------------------- ;;;###autoload (defun emms-browser () "Launch or switch to the EMMS Browser." (interactive) (emms-browser-create-or-focus emms-browser-default-browse-type)) (defun emms-browser-create-or-focus (type) "Create a new browser buffer with BROWSE-FUNC, or switch. BROWSE-FUNC should fill the buffer with something of interest. An example function is `emms-browse-by-artist'." (let ((buf (emms-browser-get-buffer)) wind) (if buf ;; if the buffer is displayed, switch the window instead (progn (setq wind (get-buffer-window buf)) (if wind (select-window wind) (switch-to-buffer buf)) (emms-browser-run-mode-hooks 'emms-browser-show-display-hook)) ;; if there's no buffer, create a new window (emms-browser-create) (emms-browse-by type)))) (defun emms-browser-create () "Create a new emms-browser buffer and start emms-browser-mode." (emms-browser-new-buffer) (emms-browser-mode) (emms-browser-run-mode-hooks 'emms-browser-show-display-hook)) (defun emms-browser-mode (&optional no-update) "A major mode for the Emms browser. \\{emms-browser-mode-map}" ;; create a new buffer (interactive) (use-local-map emms-browser-mode-map) (setq major-mode 'emms-browser-mode mode-name "Emms-Browser") (setq buffer-read-only t) (unless no-update (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." (switch-to-buffer (generate-new-buffer emms-browser-buffer-name))) (defun emms-browser-clear () "Create or switch to a browser buffer, clearing it." (let ((buf (emms-browser-get-buffer))) (if buf (progn (switch-to-buffer buf) (emms-with-inhibit-read-only-t (delete-region (point-min) (point-max)))) (emms-browser-create)))) (defun emms-browser-get-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) (error "Current buffer is not an emms-browser buffer"))) (defun emms-browser-bury-buffer () "Bury the browser buffer, running hooks." (interactive) (emms-browser-run-mode-hooks 'emms-browser-hide-display-hook) (bury-buffer)) ;; -------------------------------------------------- ;; Top-level browsing methods - by artist/album/etc ;; -------------------------------------------------- ;; Since the number of tracks may be rather large, we use a hash to ;; sort the top level elements into various categories. All ;; subelements will be stored in a bdata alist structure. (defmacro emms-browser-add-category (name type) "Create an interactive function emms-browse-by-NAME." (let ((funname (intern (concat "emms-browse-by-" name))) (funcdesc (concat "Browse by " name "."))) `(defun ,funname () ,funcdesc (interactive) (emms-browse-by ,type)))) (defun emms-browse-by (type) "Render a top level buffer based on TYPE." ;; FIXME: assumes we only browse by info-* (let* ((name (substring (symbol-name type) 5)) (modedesc (concat "Browsing by: " name)) (hash (emms-browser-make-hash-by type))) (when emms-browser-current-filter-name (setq modedesc (concat modedesc " [" emms-browser-current-filter-name "]"))) (emms-browser-clear) (rename-buffer modedesc) (emms-browser-render-hash hash type) (setq emms-browser-top-level-hash hash) (setq emms-browser-top-level-type type) (unless (> (hash-table-count hash) 0) (emms-browser-show-empty-cache-message)) (goto-char (point-min)))) (emms-browser-add-category "artist" 'info-artist) (emms-browser-add-category "composer" 'info-composer) (emms-browser-add-category "performer" 'info-performer) (emms-browser-add-category "album" 'info-album) (emms-browser-add-category "genre" 'info-genre) (emms-browser-add-category "year" 'info-year) (defun emms-browser-get-track-field (track type) "Return TYPE from TRACK. This can be customized to group different artists into one for compilations, etc." (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-albumartist) (emms-track-get track 'info-albumartistsort) (emms-track-get track 'info-artist) (emms-track-get track 'info-artistsort "<unknown 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 "<unknown 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 track) (emms-track-get track type "misc"))) (defun emms-browser-get-artist-from-path (track) (let* ((path (emms-track-get track 'name)) (dir (file-name-directory path)) (basedir (file-name-nondirectory (directory-file-name (file-name-directory dir))))) (car (split-string basedir " - ")))) (defun emms-browser-make-hash-by (type) "Make a hash, mapping with TYPE, eg artist -> tracks." (let ((hash (make-hash-table :test emms-browser-comparison-test)) field existing-entry) (maphash (lambda (path track) (unless (run-hook-with-args-until-success 'emms-browser-filter-tracks-hook track) (setq field (emms-browser-get-track-field track type)) (when field (setq existing-entry (gethash field hash)) (if existing-entry (puthash field (cons track existing-entry) hash) (puthash field (list track) hash))))) emms-cache-db) hash)) (defun emms-browser-render-hash (db type) "Render a mapping (DB) into a browser buffer." (maphash (lambda (desc data) (emms-browser-insert-top-level-entry desc data type)) db) (emms-with-inhibit-read-only-t (let ((sort-fold-case t)) (if emms-browser-alpha-sort-function (progn (goto-char (point-min)) (sort-subr nil #'forward-line #'end-of-line (lambda () (buffer-substring-no-properties (line-beginning-position) (line-end-position))) nil emms-browser-alpha-sort-function)) (sort-lines nil (point-min) (point-max)))))) (defun case-fold-string= (a b) (eq t (compare-strings a nil nil b nil nil t))) (defun case-fold-string-hash (a) (sxhash (upcase a))) (when (fboundp 'define-hash-table-test) (define-hash-table-test 'case-fold 'case-fold-string= 'case-fold-string-hash)) (defun emms-browser-insert-top-level-entry (name tracks type) "Insert a single top level entry into the buffer." (emms-browser-ensure-browser-buffer) (let ((bdata (emms-browser-make-bdata-tree type 1 tracks name))) (emms-browser-insert-format bdata))) (defun emms-browser-show-empty-cache-message () "Display some help if the cache is empty." (emms-with-inhibit-read-only-t (insert " Welcome to EMMS. There are currently no files in the EMMS database. To browse music, you need to tell EMMS where your files are. Try the following commands: M-x emms-add-directory-tree: Add all music in a directory and its subdirectories. M-x emms-add-directory: Add all music in a directory M-x emms-add-file: Add a single music file. After you have added some files, wait for EMMS to say 'all track information loaded,' then return to the browser, and hit 'b 1' to refresh."))) ;; -------------------------------------------------- ;; Building a subitem tree ;; -------------------------------------------------- (defun emms-browser-next-mapping-type (current-mapping) "Return the next sensible mapping. Eg. if CURRENT-MAPPING is currently 'info-artist, return 'info-album." (cond ((eq current-mapping 'info-artist) 'info-album) ((eq current-mapping 'info-composer) 'info-album) ((eq current-mapping 'info-performer) 'info-album) ((eq current-mapping 'info-album) 'info-title) ((eq current-mapping 'info-genre) 'info-artist) ((eq current-mapping 'info-year) 'info-artist))) (defun emms-browser-make-bdata-tree (type level tracks name) "Build a tree of browser DB elements for tracks." (emms-browser-make-bdata (emms-browser-make-bdata-tree-recurse type level tracks) name type level)) (defun emms-browser-make-bdata-tree-recurse (type level tracks) "Build a tree of alists based on a list of tracks, TRACKS. For example, if TYPE is 'info-year, return an alist like: artist1 -> album1 -> *track* 1.." (let* ((next-type (emms-browser-next-mapping-type type)) (next-level (1+ level)) alist name new-db new-tracks) ;; if we're at a leaf, the db data is a list of tracks (if (eq type 'info-title) tracks ;; otherwise, make DBs from the sub elements (setq alist (emms-browser-make-sorted-alist next-type tracks)) (mapcar (lambda (entry) (setq name (emms-browser-make-name entry next-type)) (setq new-tracks (cdr entry)) (emms-browser-make-bdata (emms-browser-make-bdata-tree-recurse next-type next-level new-tracks) name next-type next-level)) alist)))) (defun emms-browser-make-name (entry type) "Return a name for ENTRY, used for making a bdata object." (let ((key (car entry)) (track (cadr entry)) artist title) ;; only the first track (cond ((eq type 'info-title) (setq artist (emms-track-get track 'info-artist)) (setq title (emms-track-get track 'info-title)) (if (not (and artist title)) key (concat artist " - " title))) (t key)))) (defun emms-browser-track-number (track) "Return a string representation of a track number. The string will end in a space. If no track number is available, return an empty string." (let ((tracknum (emms-track-get track 'info-tracknumber))) (if (or (not (stringp tracknum)) (string= tracknum "0")) "" (concat (if (eq (length tracknum) 1) (concat "0" tracknum) tracknum))))) (defun emms-browser-disc-number (track) "Return a string representation of a track number. The string will end in a space. If no track number is available, return an empty string." (let ((discnum (emms-track-get track 'info-discnumber))) (if (or (not (stringp discnum)) (string= discnum "0")) "" discnum))) (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-year track))) (if (or (not (stringp year)) (string= year "0")) "" (concat "(" year ") ")))) (defun emms-browser-track-duration (track) "Return a string representation of a track duration. If no duration is available, return an empty string." (let ((pmin (emms-track-get track 'info-playing-time-min)) (psec (emms-track-get track 'info-playing-time-sec)) (ptot (emms-track-get track 'info-playing-time))) (cond ((and pmin psec) (format "%02d:%02d" pmin psec)) (ptot (format "%02d:%02d" (/ ptot 60) (% ptot 60))) (t "")))) (defun emms-browser-make-bdata (data name type level) "Return a browser data item from ALIST. DATA should be a list of DB items, or a list of tracks. NAME is a name for the DB item. TYPE is a category the data is organised by, such as 'info-artist. LEVEL is the number of the sublevel the db item will be placed in." (list (cons 'type type) (cons 'level level) (cons 'name name) (cons 'data data))) (defun emms-browser-make-alist (type tracks) "Make an alist mapping of TYPE -> TRACKS. Items with no metadata for TYPE will be placed in 'misc'" (let (db key existing tracknum) (dolist (track tracks) (setq key (emms-browser-get-track-field track type)) (when (eq type 'info-title) ;; try and make every track unique (setq tracknum (emms-browser-track-number track)) (if (string= tracknum "") (setq key (file-name-nondirectory (emms-track-get track 'name))) (setq key (concat tracknum key)))) (setq existing (assoc key db)) (if existing (setcdr existing (cons track (cdr existing))) (push (cons key (list track)) db))) ;; sort the entries we've built (dolist (item db) (setcdr item (nreverse (cdr item)))) db)) (defun emms-browser-make-sorted-alist (type tracks) "Return a sorted alist of TRACKS. TYPE is the metadata to make the alist by - eg. if it's 'info-artist, an alist of artists will be made." (emms-browser-sort-alist (emms-browser-make-alist type tracks) type)) ;; -------------------------------------------------- ;; BDATA accessors and predicates ;; -------------------------------------------------- (defun emms-browser-bdata-level (bdata) (cdr (assq 'level bdata))) (defun emms-browser-bdata-name (bdata) (cdr (assq 'name bdata))) (defun emms-browser-bdata-type (bdata) (cdr (assq 'type bdata))) (defun emms-browser-bdata-data (bdata) (cdr (assq 'data bdata))) (defun emms-browser-bdata-p (obj) "True if obj is a BDATA object." (consp (assq 'data obj))) ;; -------------------------------------------------- ;; Sorting expanded entries ;; -------------------------------------------------- (defmacro emms-browser-sort-cadr (sort-func) "Return a function to sort an alist using SORT-FUNC. This sorting predicate will compare the cadr of each entry. SORT-FUNC should be a playlist sorting predicate like `emms-playlist-sort-by-natural-order'." `(lambda (a b) (funcall ,sort-func (cadr a) (cadr b)))) (defmacro emms-browser-sort-car (sort-func) "Return a function to sort an alist using SORT-FUNC. This sorting predicate will compare the car of each entry. SORT-FUNC should be a playlist sorting predicate like `emms-playlist-sort-by-natural-order'." `(lambda (a b) (funcall ,sort-func (car a) (car b)))) (defun emms-browser-sort-by-track (alist) "Sort an ALIST by the tracks in each entry. Uses `emms-browser-track-sort-function'." (if emms-browser-track-sort-function (sort alist (emms-browser-sort-cadr emms-browser-track-sort-function)) alist)) (defun emms-browser-sort-by-name (alist) "Sort ALIST by keys alphabetically. Uses `emms-browser-alpha-sort-function'." (if emms-browser-alpha-sort-function (sort alist (emms-browser-sort-car emms-browser-alpha-sort-function)) alist)) (defun emms-browser-sort-by-year-or-name (alist) "Sort based on year or name." (sort alist (emms-browser-sort-cadr 'emms-browser-sort-by-year-or-name-p))) (defun emms-browser-sort-by-year-or-name-p (a b) ;; FIXME: this is a bit of a hack (let ((a-desc (concat (emms-browser-year-number a) (emms-track-get a 'info-album "misc"))) (b-desc (concat (emms-browser-year-number b) (emms-track-get b 'info-album "misc")))) (string< a-desc b-desc))) (defun emms-browser-sort-alist (alist type) "Sort ALIST using the sorting function for TYPE." (let ((sort-func (cond ((or (eq type 'info-artist) (eq type 'info-composer) (eq type 'info-performer) (eq type 'info-year) (eq type 'info-genre)) 'emms-browser-sort-by-name) ((eq type 'info-album) emms-browser-album-sort-function) ((eq type 'info-title) 'emms-browser-sort-by-track) (t (message "Can't sort unknown mapping!"))))) (funcall sort-func alist))) ;; -------------------------------------------------- ;; Subitem operations on the buffer ;; -------------------------------------------------- (defun emms-browser-bdata-at-point () "Return the bdata object at point. Includes information at point (such as album name), and metadata." (get-text-property (point-at-bol) 'emms-browser-bdata)) (defun emms-browser-data-at-point () "Return the data stored under point. This will be a list of DB items." (emms-browser-bdata-data (emms-browser-bdata-at-point))) (defun emms-browser-level-at-point () "Return the current level at point." (emms-browser-bdata-level (emms-browser-bdata-at-point))) (defun emms-browser-tracks-at-point (&optional node) "Return a list of tracks at point." (let (tracks) (dolist (node (if node node (emms-browser-data-at-point))) (if (not (emms-browser-bdata-p node)) (setq tracks (cons node tracks)) (setq tracks (append tracks (emms-browser-tracks-at-point (emms-browser-bdata-data node)))))) tracks)) (defun emms-browser-expand-one-level () "Expand the current line by one sublevel." (interactive) (let* ((data (emms-browser-data-at-point))) (save-excursion (forward-line 1) (beginning-of-line) (dolist (data-item data) (emms-browser-insert-data-item data-item))))) (defun emms-browser-insert-data-item (data-item) "Insert DATA-ITEM into the buffer. This checks DATA-ITEM's level to determine how much to indent. The line will have a property emms-browser-bdata storing subitem information." (emms-browser-insert-format data-item)) (defun emms-browser-find-entry-more-than-level (level) "Move point to next entry more than LEVEL and return point. If no entry exits, return nil. Returns point if currently on a an entry more than LEVEL." (let ((old-pos (point)) level-at-point) (forward-line 1) (setq level-at-point (emms-browser-level-at-point)) (if (and level-at-point (> level-at-point level)) (point) (goto-char old-pos) nil))) (defun emms-browser-subitems-visible () "True if there are any subentries visible point." (let ((current-level (emms-browser-level-at-point)) new-level) (save-excursion (re-search-forward "\n" nil t) (when (setq new-level (emms-browser-level-at-point)) (> new-level current-level))))) (defun emms-browser-subitems-exist () "True if it's possible to expand the current line." (not (eq (emms-browser-bdata-type (emms-browser-bdata-at-point)) 'info-title))) (defun emms-browser-move-up-level (&optional direction) "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 (and (numberp direction) direction) -1)))) (when (> current-level (or (emms-browser-level-at-point) 0)) (setq moved t) (setq continue nil))) moved)) (defun emms-browser-toggle-subitems () "Show or hide (kill) subitems under the current line." (interactive) (if (emms-browser-subitems-visible) (emms-browser-kill-subitems) (if (emms-browser-subitems-exist) (emms-browser-show-subitems) (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) (if (emms-browser-subitems-exist) (emms-browser-expand-one-level)))) (defun emms-browser-kill-subitems () "Remove all subitems under the current line. Stops at the next line at the same level, or EOF." (when (emms-browser-subitems-visible) (let ((current-level (emms-browser-level-at-point)) (next-line (point-at-bol 2))) (emms-with-inhibit-read-only-t (delete-region next-line (save-excursion (while (emms-browser-find-entry-more-than-level current-level)) (point-at-bol 2))))))) ;; -------------------------------------------------- ;; Dealing with the playlist (queuing songs, etc) ;; -------------------------------------------------- (defun emms-browser-playlist-insert-group (bdata) "Insert a group description into the playlist buffer." (let* ((type (emms-browser-bdata-type bdata)) (short-type (substring (symbol-name type) 5)) (name (emms-browser-format-line bdata 'playlist))) (with-current-emms-playlist (goto-char (point-max)) (insert name "\n")))) (defun emms-browser-playlist-insert-track (bdata) "Insert a track into the playlist buffer." (let ((name (emms-browser-format-line bdata 'playlist)) (track (car (emms-browser-bdata-data bdata)))) (with-current-emms-playlist (goto-char (point-max)) (insert name "\n")))) (defun emms-browser-playlist-insert-bdata (bdata starting-level) "Add all tracks in BDATA to the playlist." (let ((type (emms-browser-bdata-type bdata)) (name (emms-browser-bdata-name bdata)) (level (emms-browser-bdata-level bdata)) emms-browser-current-indent) ;; adjust the indentation relative to the starting level (when starting-level (setq level (- level (1- starting-level)))) ;; we temporarily rebind the current indent to the relative indent (setq emms-browser-current-indent (emms-browser-make-indent level)) ;; add a group heading? (unless (eq type 'info-title) (emms-browser-playlist-insert-group bdata)) ;; recurse or add tracks (dolist (item (emms-browser-bdata-data bdata)) (if (not (eq type 'info-title)) (emms-browser-playlist-insert-bdata item starting-level) (emms-browser-playlist-insert-track bdata))))) ;; -------------------------------------------------- ;; Expanding/contracting ;; -------------------------------------------------- (defun emms-browser-expand-to-level (level) "Expand to a depth specified by LEVEL. After expanding, jump to the currently marked entry." (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." (emms-browser-mark-entry) (goto-char (point-max)) (while (not (eq (buffer-end -1) (point))) (emms-browser-prev-non-track) (emms-browser-kill-subitems))) (defun emms-browser-find-top-level () "Move up until reaching a top-level element." (while (not (eq (emms-browser-level-at-point) 1)) (forward-line -1))) (defun emms-browser-mark-entry () "Mark the current top level entry." (save-excursion (emms-browser-find-top-level) (emms-with-inhibit-read-only-t (add-text-properties (point-at-bol) (point-at-eol) (list 'emms-browser-mark t))))) (defun emms-browser-pop-mark () "Return to the last marked entry, and remove the mark." (goto-char (point-min)) (let ((pos (text-property-any (point-min) (point-max) 'emms-browser-mark t))) (if pos (progn (goto-char pos) (emms-with-inhibit-read-only-t (remove-text-properties (point-at-bol) (point-at-eol) (list 'emms-browser-mark)))) (message "No mark saved!")))) (defun emms-browser-go-to-parent () "Move point to the parent of the current node. Return point. If at level one, return the current point." (let ((current-level (emms-browser-level-at-point))) (unless (eq current-level 1) (while (<= current-level (emms-browser-level-at-point)) (forward-line -1))) (point))) (defun emms-browser-delete-current-node () "Remove the current node, and empty parents." ;; set the data to empty (setcdr (assq 'data (emms-browser-bdata-at-point)) nil) (emms-browser-delete-node-if-empty)) (defun emms-browser-delete-node-if-empty () "If empty, remove node and empty parents." (when (zerop (length (emms-browser-data-at-point))) (save-excursion (let ((child-bdata (emms-browser-bdata-at-point)) parent-bdata parent-point) ;; record the parent's position before we delete anything (save-excursion (setq parent-point (emms-browser-go-to-parent))) ;; delete the current line (when (emms-browser-subitems-visible) (emms-browser-kill-subitems)) (emms-with-inhibit-read-only-t (goto-char (point-at-bol)) (kill-line 1)) (unless (eq (emms-browser-bdata-level child-bdata) 1) ;; remove the node from the parent, and recurse (goto-char parent-point) (setq parent-bdata (emms-browser-bdata-at-point)) (setcdr (assq 'data parent-bdata) (delq child-bdata (emms-browser-bdata-data parent-bdata))) (emms-browser-delete-node-if-empty)))))) ;; -------------------------------------------------- ;; User-visible commands ;; -------------------------------------------------- (defun emms-browser-add-tracks () "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) (let ((count (cond ((use-region-p) (1+ (- (line-number-at-pos (region-end)) (line-number-at-pos (region-beginning))))) ((numberp current-prefix-arg) current-prefix-arg) (t 1))) (first-new-track (with-current-emms-playlist (point-max)))) (when (use-region-p) (goto-char (region-beginning))) (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 () "Add all tracks at point, and play the first added track." (interactive) (let ((old-pos (emms-browser-add-tracks))) (with-current-emms-playlist (goto-char old-pos) ;; if we're sitting on a group name, move forward (unless (emms-playlist-track-at (point)) (emms-playlist-next)) (emms-playlist-select (point))) ;; FIXME: is there a better way of doing this? (emms-stop) (emms-start))) (defun emms-isearch-buffer () "Isearch through the buffer." (interactive) (goto-char (point-min)) (when (isearch-forward) (unless (emms-browser-subitems-visible) (emms-browser-show-subitems)))) (defun emms-browser-next-non-track (&optional direction) "Jump to the next non-track element." (interactive) (let ((continue t)) (while (and continue (forward-line (or direction 1))) (unless (eq (emms-browser-bdata-type (emms-browser-bdata-at-point)) 'info-title) (setq continue nil))))) (defun emms-browser-prev-non-track () "Jump to the previous non-track element." (interactive) (emms-browser-next-non-track -1)) (defun emms-browser-expand-all () "Expand everything." (interactive) (emms-browser-expand-to-level 99)) (defun emms-browser-expand-to-level-2 () "Expand all top level items one level." (interactive) (emms-browser-mark-and-collapse) (emms-browser-expand-to-level 2)) (defun emms-browser-expand-to-level-3 () "Expand all top level items two levels." (interactive) (emms-browser-mark-and-collapse) (emms-browser-expand-to-level 3)) (defun emms-browser-expand-to-level-4 () "Expand all top level items three levels." (interactive) (emms-browser-mark-and-collapse) (emms-browser-expand-to-level 4)) (defun emms-browser-collapse-all () "Collapse everything, saving and restoring the mark." (interactive) (emms-browser-mark-and-collapse) (emms-browser-pop-mark) (recenter '(4))) (defvar emms-browser-seed-pending t "Do we need to seed (random)?") (defun emms-browser-goto-random () "Move cursor to random item with the lowest visible level." (interactive) (when emms-browser-seed-pending (random t) (setq emms-browser-seed-pending nil)) (while (progn (goto-char (point-min)) (forward-line (1- (random (count-lines (point-min) (point-max))))) (emms-browser-subitems-visible)))) (defun emms-browser-view-in-dired (&optional bdata) "View the current directory in dired." ;; FIXME: currently just grabs the directory from the first track (interactive) (if bdata (if (eq (emms-browser-bdata-type bdata) 'info-title) (let* ((track (car (emms-browser-bdata-data bdata))) (path (emms-track-get track 'name)) (dir (file-name-directory path))) (find-file dir)) (emms-browser-view-in-dired (car (emms-browser-bdata-data bdata)))) (emms-browser-view-in-dired (emms-browser-bdata-at-point)))) (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 (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 () (interactive) (with-current-emms-playlist (emms-playlist-clear))) (defun emms-browser-lookup (field url) (let ((data (emms-track-get (emms-browser-bdata-first-track (emms-browser-bdata-at-point)) field))) (when data (browse-url (concat url data))))) (defun emms-browser-lookup-wikipedia (field) (emms-browser-lookup field "http://en.wikipedia.org/wiki/Special:Search?search=")) (defun emms-browser-lookup-artist-on-wikipedia () (interactive) (emms-browser-lookup-wikipedia 'info-artist)) (defun emms-browser-lookup-composer-on-wikipedia () (interactive) (emms-browser-lookup-wikipedia 'info-composer)) (defun emms-browser-lookup-performer-on-wikipedia () (interactive) (emms-browser-lookup-wikipedia 'info-performer)) (defun emms-browser-lookup-album-on-wikipedia () (interactive) (emms-browser-lookup-wikipedia 'info-album)) ;; -------------------------------------------------- ;; Linked browser and playlist windows ;; -------------------------------------------------- (defcustom emms-browser-switch-to-playlist-on-add nil "Whether to switch to to the playlist after adding files." :group 'emms-browser :type 'boolean) ;;;###autoload (defun emms-smart-browse () "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." (interactive) (add-to-list 'emms-browser-show-display-hook 'emms-browser-display-playlist) (add-to-list 'emms-browser-hide-display-hook 'emms-browser-hide-linked-window) ;; switch to the playlist window when adding tracks? (add-to-list 'emms-browser-tracks-added-hook (lambda (start-of-tracks) (interactive) (let (playlist-window) (when emms-browser-switch-to-playlist-on-add (emms-smart-browse)) ;; center on the first added track/group name (when (setq playlist-window (emms-browser-get-linked-window)) (emms-browser-with-selected-window playlist-window (goto-char start-of-tracks) (recenter '(4))))))) (let (wind buf) (cond ((eq major-mode 'emms-browser-mode) (setq buf (emms-browser-get-linked-buffer)) (setq wind (emms-browser-get-linked-window)) ;; if the playlist window is visible, select it (if wind (select-window wind) ;; otherwise display and select it (select-window (emms-browser-display-playlist)))) ((eq major-mode 'emms-playlist-mode) (setq wind (emms-browser-get-linked-window)) ;; if the playlist window is selected, and the browser is visible, ;; hide both (if wind (progn (select-window wind) (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))) (t ;; show both (emms-browser))))) (defun emms-browser-get-linked-buffer () "Return linked buffer (eg browser if playlist is selected." (cond ((eq major-mode 'emms-browser-mode) (car (emms-playlist-buffer-list))) ((eq major-mode 'emms-playlist-mode) (emms-browser-get-buffer)))) (defun emms-browser-get-linked-window () "Return linked window (eg browser if playlist is selected." (let ((buf (emms-browser-get-linked-buffer))) (when buf (get-buffer-window buf)))) (defun emms-browser-display-playlist () "A hook to show the playlist when the browser is displayed. Returns the playlist window." (interactive) (let ((pbuf (emms-browser-get-linked-buffer)) (pwin (emms-browser-get-linked-window))) ;; if the window isn't alive.. (unless (window-live-p pwin) (save-selected-window (split-window-horizontally) (other-window 1) (if pbuf (switch-to-buffer pbuf) ;; there's no playlist - create one (setq pbuf (emms-playlist-current-clear)) (switch-to-buffer pbuf)) ;; make q in the playlist window hide the linked browser (when (boundp 'emms-playlist-mode-map) (define-key emms-playlist-mode-map (kbd "q") (lambda () (interactive) (emms-browser-hide-linked-window) (bury-buffer)))) (setq pwin (get-buffer-window pbuf)))) pwin)) (defun emms-browser-hide-linked-window () "Delete a playlist or browser window when the other is hidden." (interactive) (let ((other-buf (emms-browser-get-linked-buffer)) (other-win (emms-browser-get-linked-window))) (when (and other-win (window-live-p other-win)) (delete-window other-win)) ;; bury the buffer, or it becomes visible when we hide the ;; linked buffer (bury-buffer other-buf))) ;; -------------------------------------------------- ;; Searching ;; -------------------------------------------------- (defun emms-browser-filter-cache (search-list) "Return a list of tracks that match SEARCH-LIST. SEARCH-LIST is a list of cons pairs, in the form: ((field1 field2) string) If string matches any of the fields in a cons pair, it will be included." (let (tracks) (maphash (lambda (k track) (when (emms-browser-matches-p track search-list) (push track tracks))) emms-cache-db) tracks)) (defun emms-browser-matches-p (track search-list) (let (no-match matched) (dolist (item search-list) (setq matched nil) (dolist (field (car item)) (let ((track-field (emms-track-get track field ""))) (when (and track-field (string-match (cadr item) track-field)) (setq matched t)))) (unless matched (setq no-match t))) (not no-match))) (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-buffer-name)) (emms-browser-mode t) (use-local-map emms-browser-search-mode-map) (emms-with-inhibit-read-only-t (delete-region (point-min) (point-max)))) (defun emms-browser-search (fields) "Search for STR using FIELDS." (let* ((prompt (format "Searching with %S: " fields)) (str (read-string prompt))) (emms-browser-search-buffer-go) (emms-with-inhibit-read-only-t (emms-browser-render-search (emms-browser-filter-cache (list (list fields str))))) (emms-browser-expand-all) (goto-char (point-min)))) (defun emms-browser-render-search (tracks) (let ((entries (emms-browser-make-sorted-alist 'info-artist tracks))) (dolist (entry entries) (emms-browser-insert-top-level-entry (car entry) (cdr entry) 'info-artist)))) ;; hmm - should we be doing this? (defun emms-browser-kill-search () "Kill the buffer when q is hit." (interactive) (kill-buffer (current-buffer))) (defun emms-browser-search-by-artist () (interactive) (emms-browser-search '(info-artist))) (defun emms-browser-search-by-composer () (interactive) (emms-browser-search '(info-composer))) (defun emms-browser-search-by-performer () (interactive) (emms-browser-search '(info-performer))) (defun emms-browser-search-by-title () (interactive) (emms-browser-search '(info-title))) (defun emms-browser-search-by-album () (interactive) (emms-browser-search '(info-album))) (defun emms-browser-search-by-names () (interactive) (emms-browser-search '(info-artist info-composer info-performer info-title info-album))) ;; -------------------------------------------------- ;; Album covers ;; -------------------------------------------------- (defun emms-browser--build-cover-filename () "Build `emms-browser--covers-filename'. Based on from `emms-browser-covers' (when a list) and `emms-browser-covers-file-extensions'." (setq emms-browser--covers-filename (mapcar (lambda (cover) (if (file-name-extension cover) (list cover) (mapcar (lambda (ext) (concat cover "." ext)) emms-browser-covers-file-extensions))) emms-browser-covers))) (defun emms-browser-get-cover-from-album (bdata &optional size) (cl-assert (eq (emms-browser-bdata-type bdata) 'info-album)) (let* ((track1data (emms-browser-bdata-data bdata)) (track1 (car (emms-browser-bdata-data (car track1data)))) (path (emms-track-get track1 'name))) (emms-browser-get-cover-from-path path size))) (defun emms-browser-get-cover-from-path (path &optional size) "Return a cover filename, if it exists." (unless size (setq size 'medium)) (let* ((size-idx (cond ((eq size 'small) 0) ((eq size 'medium) 1) ((eq size 'large) 2))) (cover (cond ((functionp emms-browser-covers) (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 (concat (file-name-directory path) cover))) (and (file-exists-p coverpath) coverpath))) (nth size-idx emms-browser--covers-filename)))))))) (if (and cover (file-readable-p cover)) cover ;; no cover found, use default (when emms-browser-default-covers (nth size-idx emms-browser-default-covers))))) (defun emms-browser-insert-cover (path) (insert (emms-browser-make-cover path))) (defun emms-browser-make-cover (path) (let* ((ext (file-name-extension path)) (type (cond ((string= ext "png") 'png) ((string= ext "xbm") 'xbm) ((string= ext "xpm") 'xpm) ((string= ext "pbm") 'pbm) ((string-match "e?ps" ext) 'postscript) ((string= ext "gif") 'gif) ((string= ext "tiff") 'tiff) (t 'jpeg)))) (emms-propertize " " 'display `(image :type ,type :margin 5 :file ,path) 'rear-nonsticky '(display)))) (defun emms-browser-get-cover-str (path size) (let ((cover (emms-browser-get-cover-from-path path size))) (if cover (emms-browser-make-cover cover) ;; we use a single space so that cover & no cover tracks line up ;; in a terminal " "))) ;; -------------------------------------------------- ;; Display formats ;; -------------------------------------------------- (defun emms-browser-bdata-first-track (bdata) "Return the first track from a given bdata. If > album level, most of the track data will not make sense." (let ((type (emms-browser-bdata-type bdata))) (if (eq type 'info-title) (car (emms-browser-bdata-data bdata)) ;; recurse (emms-browser-bdata-first-track (car (emms-browser-bdata-data bdata)))))) (defun emms-browser-insert-format (bdata) (emms-with-inhibit-read-only-t (insert (emms-browser-format-line bdata) "\n"))) (defun emms-browser-make-indent (level) (or emms-browser-current-indent (make-string (* 1 (1- level)) ?\s))) (defun emms-browser-format-elem (format-string elem) (cdr (assoc elem format-string))) (defun emms-browser-format-line (bdata &optional target) "Return a propertized string to be inserted in the buffer." (unless target (setq target 'browser)) (let* ((name (or (emms-browser-bdata-name bdata) "misc")) (level (emms-browser-bdata-level bdata)) (type (emms-browser-bdata-type bdata)) (indent (emms-browser-make-indent level)) (track (emms-browser-bdata-first-track bdata)) (path (emms-track-get track 'name)) (face (emms-browser-get-face bdata)) (format (emms-browser-get-format bdata target)) (props (list 'emms-browser-bdata bdata)) (format-choices `(("i" . ,indent) ("n" . ,name) ("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)) ("p" . ,(emms-track-get track 'info-performer)) ("t" . ,(emms-track-get track 'info-title)) ("D" . ,(emms-browser-disc-number track)) ("T" . ,(emms-browser-track-number track)) ("d" . ,(emms-browser-track-duration track)))) str) (when (equal type 'info-album) (setq format-choices (append format-choices `(("cS" . ,(emms-browser-get-cover-str path 'small)) ("cM" . ,(emms-browser-get-cover-str path 'medium)) ("cL" . ,(emms-browser-get-cover-str path 'large)))))) (when (functionp format) (setq format (funcall format bdata format-choices))) (setq str (with-temp-buffer (insert format) (goto-char (point-min)) (let ((start (point-min))) ;; jump over any image (when (re-search-forward "%c[SML]" nil t) (setq start (point))) ;; jump over the indent (when (re-search-forward "%i" nil t) (setq start (point))) (add-text-properties start (point-max) (list 'face face))) (buffer-string))) (setq str (emms-browser-format-spec str format-choices)) ;; give tracks a 'boost' if they're not top-level ;; (covers take up an extra space) (when (and (eq type 'info-title) (not (string= indent ""))) (setq str (concat " " str))) ;; if we're in playlist mode, add a track (when (and (eq target 'playlist) (eq type 'info-title)) (setq props (append props `(emms-track ,track)))) ;; add properties to the whole string (add-text-properties 0 (length str) props str) str)) (defun emms-browser-get-face (bdata) "Return a suitable face for BDATA." (let* ((type (emms-browser-bdata-type bdata)) (name (cond ((or (eq type 'info-year) (eq type 'info-genre)) "year/genre") ((eq type 'info-artist) "artist") ((eq type 'info-composer) "composer") ((eq type 'info-performer) "performer") ((eq type 'info-album) "album") ((eq type 'info-title) "track")))) (intern (concat "emms-browser-" name "-face")))) ;; based on gnus code (defun emms-browser-format-spec (format specification) "Return a string based on FORMAT and SPECIFICATION. FORMAT is a string containing `format'-like specs like \"bash %u %k\", while SPECIFICATION is an alist mapping from format spec characters to values. Any text properties on a %-spec itself are propagated to the text that it generates." (with-temp-buffer (insert format) (goto-char (point-min)) (while (search-forward "%" nil t) (cond ;; Quoted percent sign. ((eq (char-after) ?%) (delete-char 1)) ;; Valid format spec. ((looking-at "\\([-0-9.]*\\)\\([a-zA-Z]+\\)") (let* ((num (match-string 1)) (spec (match-string 2)) (val (cdr (assoc spec specification)))) (unless val (error "Invalid format character: %s" spec)) ;; Pad result to desired length. (let ((text (format (concat "%" num "s") val))) ;; Insert first, to preserve text properties. (insert-and-inherit text) ;; Delete the specifier body. (delete-region (+ (match-beginning 0) (length text)) (+ (match-end 0) (length text))) ;; Delete the percent sign. (delete-region (1- (match-beginning 0)) (match-beginning 0))))) ;; Signal an error on bogus format strings. (t (error "Invalid format string")))) (buffer-string))) ;; -------------------------------------------------- ;; Display formats - defaults ;; -------------------------------------------------- ;; FIXME: optional format strings would avoid having to define a ;; function for specifiers which may be empty. (defvar emms-browser-default-format "%i%n" "indent + name") ;; tracks (defvar emms-browser-info-title-format 'emms-browser-track-artist-and-title-format) (defvar emms-browser-playlist-info-title-format 'emms-browser-track-artist-and-title-format) (defun emms-browser-get-format (bdata target) (let* ((type (emms-browser-bdata-type bdata)) (target-str (or (and (eq target 'browser) "") (concat (symbol-name target) "-"))) (sym (intern (concat "emms-browser-" target-str (symbol-name type) "-format")))) (if (boundp sym) (symbol-value sym) emms-browser-default-format))) (defun emms-browser-track-artist-and-title-format (bdata fmt) (concat "%i" (let ((track (emms-browser-format-elem fmt "T"))) (if (and track (not (string= track "0"))) "%T. " "")) "%n")) ;; albums - we define two formats, one for a small cover (browser), ;; and one for a medium sized cover (playlist). (defvar emms-browser-info-album-format 'emms-browser-year-and-album-fmt) (defvar emms-browser-playlist-info-album-format 'emms-browser-year-and-album-fmt-med) (defun emms-browser-year-and-album-fmt (bdata fmt) (concat "%i%cS" (let ((year (emms-browser-format-elem fmt "y"))) (if (and year (not (string= year "0"))) "(%y) " "")) "%n")) (defun emms-browser-year-and-album-fmt-med (bdata fmt) (concat "%i%cM" (let ((year (emms-browser-format-elem fmt "y"))) (if (and year (not (string= year "0"))) "(%y) " "")) "%n")) ;; -------------------------------------------------- ;; Display faces ;; -------------------------------------------------- (defmacro emms-browser-make-face (name dark-col light-col height) (let ((face-name (intern (concat "emms-browser-" name "-face")))) `(defface ,face-name '((((class color) (background dark)) (:foreground ,dark-col :height ,height)) (((class color) (background light)) (:foreground ,light-col :height ,height)) (((type tty) (class mono)) (:inverse-video t)) (t (:background ,dark-col))) ,(concat "Face for " name " in a browser/playlist buffer.") :group 'emms-browser-mode))) (emms-browser-make-face "year/genre" "#aaaaff" "#444477" 1.5) (emms-browser-make-face "artist" "#aaaaff" "#444477" 1.3) (emms-browser-make-face "composer" "#aaaaff" "#444477" 1.3) (emms-browser-make-face "performer" "#aaaaff" "#444477" 1.3) (emms-browser-make-face "album" "#aaaaff" "#444477" 1.1) (emms-browser-make-face "track" "#aaaaff" "#444477" 1.0) ;; -------------------------------------------------- ;; Filtering ;; -------------------------------------------------- (defvar emms-browser-filters nil "A list of available filters.") (defmacro emms-browser-make-filter (name func) "Make a user-level function for filtering tracks. This: - defines an interactive function M-x emms-browser-show-NAME. - defines a variable emms-browser-filter-NAME of (name . func). - adds the filter to emms-browser-filters." (let ((funcnam (intern (concat "emms-browser-show-" name))) (var (intern (concat "emms-browser-filter-" name))) (desc (concat "Filter the cache using rule '" name "'"))) `(progn (defvar ,var nil ,desc) (setq ,var (cons ,name ,func)) (add-to-list 'emms-browser-filters ,var) (defun ,funcnam () ,desc (interactive) (emms-browser-refilter ,var))))) (defun emms-browser-set-filter (filter) "Set the current filter to be used on next update. This does not refresh the current buffer." (setq emms-browser-filter-tracks-hook (cdr filter)) (setq emms-browser-current-filter-name (car filter)) (run-hooks 'emms-browser-filter-changed-hook)) (defun emms-browser-refilter (filter) "Filter and render the top-level tracks." (emms-browser-set-filter filter) (emms-browse-by (or emms-browser-top-level-type emms-browser-default-browse-type))) (defun emms-browser-next-filter (&optional reverse) "Redisplay with the next filter." (interactive) (let* ((list (if reverse (reverse emms-browser-filters) emms-browser-filters)) (key emms-browser-current-filter-name) (next (cadr (member (assoc key list) list)))) ;; wrapped (unless next (setq next (car list))) (emms-browser-refilter next))) (defun emms-browser-previous-filter () "Redisplay with the previous filter." (interactive) (emms-browser-next-filter t)) (defun emms-browser-filter-only-dir (path) "Generate a function which checks if a track is in path. If the track is not in path, return t." `(lambda (track) (not (string-match ,(concat "^" (expand-file-name path)) (emms-track-get track 'name))))) (defun emms-browser-filter-only-type (type) "Generate a function which checks a track's type. If the track is not of TYPE, return t." `(lambda (track) (not (eq (quote ,type) (emms-track-get track 'type))))) ;; seconds in a day (* 60 60 24) = 86400 (defun emms-browser-filter-only-recent (days) "Show only tracks played within the last number of DAYS." `(lambda (track) (let ((min-date (time-subtract (current-time) (seconds-to-time (* ,days 86400)))) last-played) (not (and (setq last-played (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))))) (defvar emms-browser--cache-hash nil "Cache for `emms-browser-cache-thumbnail-async'.") (defun emms-browser-cache-thumbnail-async (dir size) "Like `emms-browser-cache-thumbnail' but caches queries for faster lookups. The drawback is that if changes are made to the covers in DIR after `emms-browser-cache-thumbnail-async' queried them, it won't be taken into account. Call `emms-browser-clear-cache-hash' to refresh the cache." (unless emms-browser--cache-hash (setq emms-browser--cache-hash (make-hash-table :test 'equal))) (let* ((key (cons dir size)) (val (gethash key emms-browser--cache-hash))) (or val (puthash key (emms-browser-cache-thumbnail dir size) emms-browser--cache-hash)))) (defun emms-browser-clear-cache-hash () "Resets `emms-browser-cache-thumbnail-async' cache. This is useful if there were changes on disk after `emms-browser-cache-thumbnail-async' first cached them." (interactive) (clrhash emms-browser--cache-hash)) (provide 'emms-browser) ;;; emms-browser.el ends here �����������������������������������������������������������������������������������������������������������������������������emms-6.00/emms-cache.el�����������������������������������������������������������������������������0000664�0001750�0001750�00000014475�13746063641�013147� 0����������������������������������������������������������������������������������������������������ustar �yrk�����������������������������yrk��������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������;;; emms-cache.el --- persistence for emms-track ;; Copyright (C) 2006, 2007, 2008, 2009 Free Software Foundation, Inc. ;; Author: Damien Elmes <emacs@repose.cx> ;; Keywords: emms, mp3, mpeg, multimedia ;; 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, 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; see the file COPYING. If not, write to the ;; Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, ;; Boston, MA 02110-1301, USA. ;;; Commentary: ;; The cache is a mapping of a full path name to information, and so ;; it is invalidated when you rename or move files about. It also ;; does not differentiate between file or uri tracks. ;; Because cache lookups are much faster than disk access, this works ;; much better with a emms-later-do-interval of something like 0.001. Also ;; consider using synchronous mode, as it's quite fast now. ;; This code is activated by (emms-standard) and above. ;; To activate it by hand, use: ;; (emms-cache 1) ;;; Code: (require 'emms) (require 'emms-info) (when (fboundp 'define-hash-table-test) (define-hash-table-test 'string-hash 'string= 'sxhash)) (defvar emms-cache-db (make-hash-table :test (if (fboundp 'define-hash-table-test) 'string-hash 'equal)) "A mapping of paths to file info. This is used to cache over emacs sessions.") (defvar emms-cache-dirty nil "True if the cache has been updated since init.") (defcustom emms-cache-file (concat (file-name-as-directory emms-directory) "cache") "A file used to store cached file information over sessions." :group 'emms :type 'file) (defcustom emms-cache-file-coding-system 'utf-8 "Coding system used for saving `emms-cache-file'." :group 'emms :type 'coding-system) (defun emms-cache (arg) "Turn on Emms caching if ARG is positive, off otherwise." (interactive "p") (if (and arg (> arg 0)) (progn (unless emms-cache-dirty (emms-cache-restore)) (unless noninteractive (add-hook 'kill-emacs-hook 'emms-cache-save)) (setq emms-cache-get-function 'emms-cache-get) (setq emms-cache-set-function 'emms-cache-set) (setq emms-cache-modified-function 'emms-cache-dirty)) (remove-hook 'kill-emacs-hook 'emms-cache-save) (setq emms-cache-get-function nil) (setq emms-cache-set-function nil) (setq emms-cache-modified-function nil))) ;;;###autoload (defun emms-cache-enable () "Enable caching of Emms track data." (interactive) (emms-cache 1) (message "Emms cache enabled")) ;;;###autoload (defun emms-cache-disable () "Disable caching of Emms track data." (interactive) (emms-cache -1) (message "Emms cache disabled")) ;;;###autoload (defun emms-cache-toggle () "Toggle caching of Emms track data." (interactive) (if emms-cache-get-function (emms-cache-disable) (emms-cache-enable))) (defsubst emms-cache-dirty (&rest ignored) "Mark the cache as dirty." (setq emms-cache-dirty t)) (defun emms-cache-get (type path) "Return a cache element for PATH, or nil." (gethash path emms-cache-db)) ;; Note we ignore TYPE, as it's stored in TRACK (defun emms-cache-set (type path track) "Set PATH to TRACK in the cache." (puthash path track emms-cache-db) (emms-cache-dirty)) (defun emms-cache-del (path) "Remove a track from the cache, with key PATH." (remhash path emms-cache-db) (emms-cache-dirty)) (defun emms-cache-save () "Save the track cache to a file." (interactive) (when emms-cache-dirty (message "Saving emms track cache...") (set-buffer (get-buffer-create " emms-cache ")) (erase-buffer) (insert (concat ";;; .emms-cache -*- mode: emacs-lisp; coding: " (symbol-name emms-cache-file-coding-system) "; -*-\n")) (maphash (lambda (k v) (insert (format "(puthash %S '%S emms-cache-db)\n" k v))) emms-cache-db) (when (fboundp 'set-buffer-file-coding-system) (set-buffer-file-coding-system emms-cache-file-coding-system)) (unless (file-directory-p (file-name-directory emms-cache-file)) (make-directory (file-name-directory emms-cache-file))) (write-region (point-min) (point-max) emms-cache-file) (kill-buffer (current-buffer)) (message "Saving emms track cache...done") (setq emms-cache-dirty nil))) (defun emms-cache-restore () "Restore the track cache from a file." (interactive) (load emms-cache-file t nil t) (setq emms-cache-dirty nil)) (defun emms-cache-sync () "Sync the cache with the data on disc. Remove non-existent files, and update data for files which have been modified." (interactive) (message "Syncing emms track cache...") (let (removed) (maphash (lambda (path track) (when (eq (emms-track-get track 'type) 'file) ;; if no longer here, remove (if (not (file-exists-p path)) (progn (remhash path emms-cache-db) (setq removed t)) (let ((file-mtime (emms-info-track-file-mtime track)) (info-mtime (emms-track-get track 'info-mtime))) (when (or (not info-mtime) (emms-time-less-p info-mtime file-mtime)) (run-hook-with-args 'emms-info-functions track)))))) emms-cache-db) (when removed (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 ���������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������emms-6.00/emms-compat.el����������������������������������������������������������������������������0000664�0001750�0001750�00000013332�13746063641�013356� 0����������������������������������������������������������������������������������������������������ustar �yrk�����������������������������yrk��������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������;;; emms-compat.el --- Compatibility routines for EMMS ;; Copyright (C) 2005, 2006, 2007, 2008, 2009 Free Software Foundation, Inc. ;; Author: Michael Olson <mwolson@gnu.org> ;; 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, 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; see the file COPYING. If not, write to the ;; Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, ;; Boston, MA 02110-1301, USA. ;;; Commentary: ;; These are functions and macros that EMMS needs in order to be ;; compatible with various Emacs and XEmacs versions. ;;; Code: ;;; Miscellaneous (defun emms-propertize (string &rest properties) (if (fboundp 'propertize) (apply #'propertize string properties) (set-text-properties 0 (length string) properties string) string)) ;; Emacs accepts three arguments to `make-obsolete', but the XEmacs ;; version only takes two arguments (defun emms-make-obsolete (old-name new-name when) "Make the byte-compiler warn that OLD-NAME is obsolete. The warning will say that NEW-NAME should be used instead. WHEN should be a string indicating when the function was first made obsolete, either the file's revision number or an EMMS release version number." (if (featurep 'xemacs) (make-obsolete old-name new-name) (make-obsolete old-name new-name when))) ;;; Time and timers (defun emms-cancel-timer (timer) "Cancel the given TIMER." (when timer (cond ((fboundp 'cancel-timer) (cancel-timer timer)) ((fboundp 'delete-itimer) (delete-itimer timer))))) (defun emms-time-less-p (t1 t2) "Say whether time T1 is less than time T2." (or (< (car t1) (car t2)) (and (= (car t1) (car t2)) (< (nth 1 t1) (nth 1 t2))))) ;;; Highline (defun emms-activate-highlighting-mode () "Activate highline mode." (if (featurep 'xemacs) (progn (require 'highline) (highline-local-mode 1)) (progn (require 'hl-line) (hl-line-mode 1)))) (declare-function hl-line-highlight "" nil) ;; called from emms-lyrics (defun emms-line-highlight () "Highlight the current line. You must call emms-activate-highlighting-mode beforehand." (if (featurep 'xemacs) (highline-highlight-current-line) (hl-line-highlight))) ;;; Movement and position (defun emms-move-beginning-of-line (arg) "Move point to beginning of current line as displayed. If there's an image in the line, this disregards newlines which are part of the text that the image rests on." (if (fboundp 'move-beginning-of-line) (move-beginning-of-line arg) (if (numberp arg) (forward-line (1- arg)) (forward-line 0)))) (defun emms-line-number-at-pos (&optional pos) "Return (narrowed) buffer line number at position POS. If POS is nil, use current buffer location." (if (fboundp 'line-number-at-pos) (line-number-at-pos pos) (let ((opoint (or pos (point))) start) (save-excursion (goto-char (point-min)) (setq start (point)) (goto-char opoint) (forward-line 0) (1+ (count-lines start (point))))))) ;;; Regular expression matching (defun emms-replace-regexp-in-string (regexp replacement text &optional fixedcase literal) "Replace REGEXP with REPLACEMENT in TEXT. If fourth arg FIXEDCASE is non-nil, do not alter case of replacement text. If fifth arg LITERAL is non-nil, insert REPLACEMENT literally." (cond ((fboundp 'replace-regexp-in-string) (replace-regexp-in-string regexp replacement text fixedcase literal)) ((and (featurep 'xemacs) (fboundp 'replace-in-string)) (replace-in-string text regexp replacement literal)) (t (let ((repl-len (length replacement)) start) (save-match-data (while (setq start (string-match regexp text start)) (setq start (+ start repl-len) text (replace-match replacement fixedcase literal text))))) text))) (defun emms-match-string-no-properties (num &optional string) (if (fboundp 'match-string-no-properties) (match-string-no-properties num string) (match-string num string))) ;;; Common Lisp (defun emms-delete-if (predicate seq) "Remove all items satisfying PREDICATE in SEQ. This is a destructive function: it reuses the storage of SEQ whenever possible." ;; remove from car (while (when (funcall predicate (car seq)) (setq seq (cdr seq)))) ;; remove from cdr (let ((ptr seq) (next (cdr seq))) (while next (when (funcall predicate (car next)) (setcdr ptr (if (consp next) (cdr next) nil))) (setq ptr (cdr ptr)) (setq next (cdr ptr)))) seq) (defun emms-find-if (predicate seq) "Find the first item satisfying PREDICATE in SEQ. Return the matching item, or nil if not found." (catch 'found (dolist (el seq) (when (funcall predicate el) (throw 'found el))))) (defun emms-remove-if-not (predicate seq) "Remove all items not satisfying PREDICATE in SEQ. This is a non-destructive function; it makes a copy of SEQ to avoid corrupting the original SEQ." (let (newseq) (dolist (el seq) (when (funcall predicate el) (setq newseq (cons el newseq)))) (nreverse newseq))) (provide 'emms-compat) ;;; emms-compat.el ends here ������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������emms-6.00/emms-cue.el�������������������������������������������������������������������������������0000664�0001750�0001750�00000011166�13746063641�012652� 0����������������������������������������������������������������������������������������������������ustar �yrk�����������������������������yrk��������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������;;; emms-cue.el --- Recognize cue sheet file ;; Copyright (C) 2009 Free Software Foundation, Inc. ;; Author: William Xu <william.xwl@gmail.com> ;; 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: ;; By parsing cue file, we will be able to play next/previous track from a ;; single .ape or .flac file. ;;; Code: (require 'emms-playing-time) (require 'emms-info) (defun emms-cue-next () "Play next track from .cue file." (interactive) (let ((cue-track (emms-cue-next-track))) (if (cdr cue-track) (progn (emms-seek-to (cdr cue-track)) (message "Will play: %s" (car cue-track))) (message "Nothing to seek or missing .cue file?")))) (defun emms-cue-previous () "Play previous track from .cue file." (interactive) (let ((cue-track (emms-cue-previous-track))) (if (cdr cue-track) (progn (emms-seek-to (cdr cue-track)) (message "Will play: %s" (car cue-track))) (message "Nothing to seek or missing .cue file?")))) (defun emms-cue-next-track (&optional previous-p) "Get title and offset of next track from .cue file. When PREVIOUS-P is t, get previous track info instead." (let* ((track (emms-playlist-current-selected-track)) (name (emms-track-get track 'name)) (cue (concat (file-name-sans-extension name)".cue"))) (when (file-exists-p cue) (with-temp-buffer (emms-insert-file-contents cue) (save-excursion (if previous-p (goto-char (point-max)) (goto-char (point-min))) (let ((offset nil) (title "") ;; We should search one more track far when getting previous ;; track. (one-more-track previous-p)) (while (and (not offset) (funcall (if previous-p 'search-backward-regexp 'search-forward-regexp) "INDEX 01 \\([0-9][0-9]\\):\\([0-9][0-9]\\):\\([0-9][0-9]\\)" nil t 1)) (let* ((min (string-to-number (match-string-no-properties 1))) (sec (string-to-number (match-string-no-properties 2))) (msec (string-to-number (match-string-no-properties 3))) (total-sec (+ (* min 60) sec (/ msec 100.0)))) (when (funcall (if previous-p '> '<) emms-playing-time total-sec) (if (not one-more-track) (progn (setq offset total-sec) (when (search-backward-regexp "TITLE \"\\(.*\\)\"" nil t 1) (setq title (match-string-no-properties 1)))) (setq one-more-track nil))))) (cons title offset))))))) (defun emms-cue-previous-track () "See `emms-cue-next-track'." (emms-cue-next-track t)) (defun emms-info-cueinfo (track) "Add track information to TRACK. This is a useful element for `emms-info-functions'." (when (and (eq 'file (emms-track-type track)) (string-match "\\.\\(ape\\|flac\\)\\'" (emms-track-name track))) (let ((cue (concat (file-name-sans-extension (emms-track-name track)) ".cue"))) (when (file-exists-p cue) (with-temp-buffer (emms-insert-file-contents cue) (save-excursion (mapc (lambda (i) (goto-char (point-min)) (when (let ((case-fold-search t)) (search-forward-regexp (concat (car i) " \\(.*\\)") nil t 1)) (emms-track-set track (cdr i) (replace-regexp-in-string "\\`\"\\|\"\\'" "" (match-string 1))))) '(("performer" . info-artist) ("title" . info-album) ("title" . info-title) ("rem date" . info-year))))))))) (provide 'emms-cue) ;;; emms-cue.el ends here ����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������emms-6.00/emms-history.el���������������������������������������������������������������������������0000664�0001750�0001750�00000011406�13746063641�013574� 0����������������������������������������������������������������������������������������������������ustar �yrk�����������������������������yrk��������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������;;; emms-history.el -- save all playlists when exiting emacs ;; Copyright (C) 2006, 2007, 2008, 2009 Free Software Foundation, Inc. ;; ;; Author: Ye Wenbin <wenbinye@163.com> ;; This file is part of EMMS. ;; This program is free software; you can redistribute it and/or modify ;; it under the terms of the GNU General Public License as published by ;; the Free Software Foundation; either version 3, or (at your option) ;; any later version. ;; ;; This program is distributed in the hope that it will be useful, ;; but WITHOUT ANY WARRANTY; without even the implied warranty of ;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ;; GNU General Public License for more details. ;; ;; You should have received a copy of the GNU General Public License ;; along with this program; if not, write to the Free Software ;; Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. ;;; Commentary: ;; Saves all playlists when you close emacs. When you start it up again use ;; M-x emms-history-load to restore all saved playlists. ;; To use it put the following into your ~/.emacs: ;; ;; (require 'emms-history) ;; ;; If all playlists should be restored on startup add this, too: ;; ;; (emms-history-load) ;;; Code: (require 'emms) (defgroup emms-history nil "Saving and restoring all playlists when closing/restarting Emacs." :prefix "emms-history-" :group 'emms) (defcustom emms-history-file (concat (file-name-as-directory emms-directory) "history") "The file to save playlists in." :type 'string :group 'emms-history) (defcustom emms-history-start-playing nil "If non-nil emms starts playing the current track after `emms-history-load' was invoked." :type 'boolean :group 'emms-history) (defcustom emms-history-file-coding-system 'utf-8 "Coding system used for saving `emms-history-file'." :type 'coding-system :group 'emms-history) (defun emms-history-save () "Save all playlists that are open in this Emacs session." (interactive) (when (stringp emms-history-file) (let ((oldbuf emms-playlist-buffer) ;; print with no limit print-length print-level emms-playlist-buffer playlists) (save-excursion (dolist (buf (emms-playlist-buffer-list)) (set-buffer buf) (when (> (buffer-size) 0) ; make sure there is track in the buffer (setq emms-playlist-buffer buf playlists (cons (list (buffer-name) (or (and emms-playlist-selected-marker (marker-position emms-playlist-selected-marker)) (point-min)) (save-restriction (widen) (nreverse (emms-playlist-tracks-in-region (point-min) (point-max))))) playlists)))) (with-temp-buffer (insert (concat ";;; emms history -*- mode: emacs-lisp; coding: " (symbol-name emms-history-file-coding-system) "; -*-\n")) (insert "(\n;; active playlist\n") (prin1 (buffer-name oldbuf) (current-buffer)) (insert "\n;; playlists: ((BUFFER_NAME SELECT_POSITION TRACKS) ...)\n") (prin1 playlists (current-buffer)) (insert "\n;; play method\n") (prin1 `((emms-repeat-track . ,emms-repeat-track) (emms-repeat-playlist . ,emms-repeat-playlist)) (current-buffer)) (insert "\n)") (write-file emms-history-file)))))) (unless noninteractive (add-hook 'kill-emacs-hook 'emms-history-save)) (defun emms-history-load () "Restore all playlists in `emms-history-file'." (interactive) (when (and (stringp emms-history-file) (file-exists-p emms-history-file)) (let (history buf) (with-temp-buffer (emms-insert-file-contents emms-history-file) (setq history (read (current-buffer))) (dolist (playlist (cadr history)) (with-current-buffer (emms-playlist-new (car playlist)) (setq emms-playlist-buffer (current-buffer)) (if (string= (car playlist) (car history)) (setq buf (current-buffer))) (mapc 'emms-playlist-insert-track (nth 2 playlist)) (run-hooks 'emms-playlist-source-inserted-hook) (ignore-errors (emms-playlist-select (cadr playlist))))) (setq emms-playlist-buffer buf) (dolist (method (nth 2 history)) (set (car method) (cdr method))) (ignore-errors (when emms-history-start-playing (emms-start))))))) (provide 'emms-history) ;;; emms-history.el ends here ����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������emms-6.00/emms-i18n.el������������������������������������������������������������������������������0000664�0001750�0001750�00000015725�13746063641�012662� 0����������������������������������������������������������������������������������������������������ustar �yrk�����������������������������yrk��������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������;;; emms-i18n.el --- functions for handling coding systems ;; Copyright (C) 2006, 2007, 2008, 2009 Free Software Foundation, Inc. ;; Author: Ye Wenbin <wenbinye@163.com> ;; This file is part of EMMS. ;; This program is free software; you can redistribute it and/or ;; modify it under the terms of the GNU General Public License as ;; published by the Free Software Foundation; either version 3, or (at ;; your option) any later version. ;; This program is distributed in the hope that it will be useful, but ;; WITHOUT ANY WARRANTY; without even the implied warranty of ;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU ;; General Public License for more details. ;; You should have received a copy of the GNU General Public License ;; along with this program; if not, write to the Free Software ;; Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. ;;; Commentary: ;; When reading from process, first check the car part of ;; `emms-i18n-default-coding-system'; if non-nil, use this for ;; decoding, and never detect coding system; if nil, first call ;; `emms-i18n-coding-detect-functions' to get coding system, if ;; success, decode the result, otherwise, use ;; `emms-i18n-detect-coding-function', the Emacs detect coding ;; function, if the coding detected is not in ;; `emms-i18n-never-used-coding-system', decode it, otherwise use ;; locale-coding-system. ;; When writing/sending data to process, first check the cdr part of ;; `emms-i18n-default-coding-system', if non-nil, use this to encode ;; data, otherwise do nothing, that means use ;; `default-process-coding-system' or `process-coding-system-alist' to ;; encode data. ;; Put this file into your load-path and the following into your ;; ~/.emacs: ;; (require 'emms-i18n) ;;; Code: (provide 'emms-i18n) ;; TODO: Use defcustom. (defvar emms-i18n-never-used-coding-system '(raw-text undecided) "If the `emms-i18n-coding-detect-functions' return a coding system in this list, use `emms-i18n-default-coding-system' instead.") ;; TODO: Use defcustom. (defvar emms-i18n-coding-system-for-read 'utf-8 "If coding detect fails, use this for decoding.") ;; TODO: Use defcustom. (defvar emms-i18n-default-coding-system '(no-conversion . no-conversion) "If non-nil, use this for decoding and encoding.") ;; TODO: Use defcustom. (defvar emms-i18n-coding-detect-functions nil "A list of functions to call to detect codings.") ;; TODO: Use defcustom. (defvar emms-i18n-detect-max-size 10000 "Maximum amount of bytes to detect the coding system. nil means to scan the whole buffer.") (defun emms-i18n-iconv (from to str) "Convert string STR from FROM coding to TO coding." (if (and from to) (decode-coding-string (encode-coding-string str to) from) str)) (defun emms-i18n-iconv-region (beg end from to) (when (and from to) (save-restriction (narrow-to-region beg end) (encode-coding-region (point-min) (point-max) to) (decode-coding-region (point-min) (point-max) from)))) (defun emms-i18n-iconv-buffer (from to &optional buf) "Convert buffer BUF from FROM coding to TO coding. BUF defaults to the current buffer." (save-excursion (and buf (set-buffer buf)) (emms-i18n-iconv-region (point-min) (point-max) from to))) (defun emms-i18n-set-default-coding-system (read-coding write-coding) "Set `emms-i18n-default-coding-system'." (interactive "zSet coding system for read: \nzSet coding system for write: ") (setq emms-i18n-default-coding-system (cons (and (coding-system-p read-coding) read-coding) (and (coding-system-p write-coding) write-coding))) (message (concat (if (car emms-i18n-default-coding-system) (format "The coding system for reading is %S." (car emms-i18n-default-coding-system)) "Good, you want me to detect the coding system!") (format " The coding system for writing is %S." (or (cdr emms-i18n-default-coding-system) (cdr default-process-coding-system)))))) (defun emms-i18n-call-process-simple (&rest args) "Run a program and return the program result. If the car part of `emms-i18n-default-coding-system' is non-nil, the program result will be decoded using the car part of `emms-i18n-default-coding-system'. Otherwise, use `emms-i18n-coding-detect-functions' to detect the coding system of the result. If the `emms-i18n-coding-detect-functions' failed, use `emms-i18n-detect-coding-function' to detect coding system. If all the coding systems are nil or in `emms-i18n-never-used-coding-system', decode the result using `emms-i18n-coding-system-for-read'. ARGS are the same as in `call-process', except BUFFER should always have the value t. Otherwise the coding detection will not be performed." (let ((default-process-coding-system (copy-tree default-process-coding-system)) (process-coding-system-alist nil) exit pos) (when (eq (nth 2 args) 't) (setcar default-process-coding-system (car emms-i18n-default-coding-system)) (setq pos (point))) (setq exit (apply 'call-process args)) (when (and (eq (nth 2 args) 't) (eq (car emms-i18n-default-coding-system) 'no-conversion)) (save-restriction (narrow-to-region pos (point)) (decode-coding-region (point-min) (point-max) (emms-i18n-detect-buffer-coding-system)))) exit)) ;; TODO: Is this function useful? (defun emms-i18n-call-process (&rest args) "Run the program like `call-process'. If the cdr part of `emms-i18n-default-coding-system' is non-nil, the string in ARGS will be encoded by the cdr part of `emms-i18n-default-coding-system'; otherwise, all parameters are simply passed to `call-process'." (with-temp-buffer (if (cdr emms-i18n-default-coding-system) (let ((default-process-coding-system emms-i18n-default-coding-system) (process-coding-system-alist nil)) (apply 'call-process args)) (apply 'call-process args)))) (defun emms-i18n-detect-coding-function (size) (detect-coding-region (point) (+ (if (null emms-i18n-detect-max-size) size (min size emms-i18n-detect-max-size)) (point)) t)) (defun emms-i18n-detect-buffer-coding-system (&optional buf) "Before calling this function, make sure the buffer is literal." (let ((size (- (point-max) (point-min))) (func (append emms-i18n-coding-detect-functions 'emms-i18n-detect-coding-function)) coding) (save-excursion (and buf (set-buffer buf)) (goto-char (point-min)) (when (> size 0) (setq coding (run-hook-with-args-until-success 'func size)) (if (member (coding-system-base coding) emms-i18n-never-used-coding-system) (setq coding (emms-i18n-detect-coding-function size)))) (if (or (null coding) (member (coding-system-base coding) emms-i18n-never-used-coding-system)) emms-i18n-coding-system-for-read coding)))) ;;; emms-i18n.el ends here �������������������������������������������emms-6.00/emms-info-exiftool.el���������������������������������������������������������������������0000664�0001750�0001750�00000006027�13746063641�014660� 0����������������������������������������������������������������������������������������������������ustar �yrk�����������������������������yrk��������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������;;; emms-info-exiftool.el --- info-method for EMMS using exiftool -*- lexical-binding: t; -*- ;; Copyright (C) 2020 Free Software Foundation, Inc. ;; Author: Yoni Rabkin (yrk@gnu.org) ;; Keywords: multimedia ;; 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; see the file COPYING.. If not, see ;; <https://www.gnu.org/licenses/>. ;;; Commentary: ;; (setq emms-info-functions '(emms-info-exiftool)) ;; To use this you would need to have exiftool installed on your ;; system. ;;; Code: (require 'emms-info) (require 'json) (defgroup emms-info-exiftool nil "Options for EMMS." :group 'emms-info) (defvar emms-info-exiftool-field-map '((info-album . Album) (info-artist . Artist) (info-title . Title) (info-tracknumber . TrackNumber) (info-composer . Composer) (info-year . Year) (info-discnumber . Discnumber) (info-genre . Genre) (info-note . Comment) (info-playing-time . Duration) (info-albumartist . Albumartist)) "Mapping for exiftool output.") ;; should only be called inside a buffer containing the json output of ;; exiftool (defun emms-info-exiftool-time () "Convert from exiftool-time to seconds." (save-excursion (goto-char (point-min)) (if (re-search-forward "duration.+\\([0-9]+\\):\\([0-9]+\\):\\([0-9]+\\)" (point-max) t) (let ((hours (string-to-number (match-string-no-properties 1))) (minutes (string-to-number (match-string-no-properties 2))) (seconds (string-to-number (match-string-no-properties 3)))) (+ (* hours 60 60) (* minutes 60) seconds)) 0))) (defun emms-info-exiftool (track) "Set TRACK info using exiftool." (when (eq (emms-track-type track) 'file) (with-temp-buffer (when (zerop (let ((coding-system-for-read 'utf-8)) (call-process "exiftool" nil '(t nil) nil "-json" (emms-track-name track)))) (goto-char (point-min)) (condition-case nil (let ((json-fields (elt (json-read) 0))) (mapc (lambda (field-map) (let ((emms-field (car field-map)) (exiftool-field (cdr field-map))) (let ((track-field (assoc exiftool-field json-fields))) (when track-field (emms-track-set track emms-field (cond ((eq emms-field 'info-playing-time) (emms-info-exiftool-time)) (t (cdr track-field)))))))) emms-info-exiftool-field-map)) (error (message "error while reading track info"))) track)))) (provide 'emms-info-exiftool) ;;; emms-info-exiftool.el ends here ���������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������emms-6.00/emms-info-libtag.el�����������������������������������������������������������������������0000664�0001750�0001750�00000007403�13746063641�014270� 0����������������������������������������������������������������������������������������������������ustar �yrk�����������������������������yrk��������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������;;; emms-info-libtag.el --- Info-method for EMMS using libtag ;; Copyright (C) 2003, 2004, 2005, 2006, 2007, 2008, ;; 2009 Free Software Foundation, Inc. ;; Authors: Ulrik Jensen <terryp@daimi.au.dk> ;; Jorgen Schäfer <forcer@forcix.cx> ;; Keywords: ;; 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, 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; see the file COPYING. If not, write to the ;; Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, ;; Boston, MA 02110-1301, USA. ;;; Commentary: ;; This code has been adapted from code found in mp3player.el, written ;; by Jean-Philippe Theberge (jphiltheberge@videotron.ca), Mario ;; Domgoergen (kanaldrache@gmx.de) and Jorgen Schäfer ;; <forcer@forcix.cx> ;; To activate this method for getting info, use something like: ;; (require 'emms-info-libtag) ;; (add-to-list 'emms-info-functions 'emms-info-libtag) ;; Note that you should remove emms-info-mp3info and emms-info-ogginfo ;; from the emms-info-functions list if you want to avoid ;; conflicts. For example, to set libtag as your exclusive info ;; provider: ;; (setq emms-info-functions '(emms-info-libtag)) ;; You may have to compile the program from source. ;; Make sure that you have libtag installed. ;; In the EMMS source directory do ;; ;; make emms-print-metadata ;; ;; and copy src/emms-print-metadata to your PATH. ;; If compilation fails and libtag is installed, you may have to ;; change the line ;; ;; #include <tag_c.h> ;; ;; to the correction location, e.g. ;; ;; #include <taglib/tag_c.h> ;;; Code: (require 'emms-info) (defgroup emms-info-libtag nil "Options for EMMS." :group 'emms-info) (defvar emms-info-libtag-coding-system 'utf-8) (defcustom emms-info-libtag-program-name "emms-print-metadata" "Name of emms-info-libtag program." :type '(string) :group 'emms-info-libtag) (defcustom emms-info-libtag-known-extensions (regexp-opt '("mp3" "mp4" "m4a" "ogg" "flac" "spx" "wma")) "Regexp of known extensions compatible with `emms-info-libtag-program-name'. Case is irrelevant." :type '(string) :group 'emms-info-libtag) (defun emms-info-libtag (track) (when (and (eq 'file (emms-track-type track)) (let ((case-fold-search t)) (string-match emms-info-libtag-known-extensions (emms-track-name track)))) (with-temp-buffer (when (zerop (let ((coding-system-for-read 'utf-8)) (call-process emms-info-libtag-program-name nil '(t nil) nil (emms-track-name track)))) (goto-char (point-min)) ;; Crush the trailing whitespace (while (re-search-forward "[[:space:]]+$" nil t) (replace-match "" nil nil)) (goto-char (point-min)) (while (looking-at "^\\([^=\n]+\\)=\\(.*\\)$") (let ((name (intern-soft (match-string 1))) (value (match-string 2))) (when (> (length value) 0) (emms-track-set track name (if (eq name 'info-playing-time) (string-to-number value) value)))) (forward-line 1)))))) (provide 'emms-info-libtag) ;;; emms-info-libtag.el ends here �������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������emms-6.00/emms-info-metaflac.el���������������������������������������������������������������������0000664�0001750�0001750�00000007457�13746063641�014613� 0����������������������������������������������������������������������������������������������������ustar �yrk�����������������������������yrk��������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������;;; emms-info-metaflac.el --- Info-method for EMMS using metaflac ;; Copyright (C) 2006, 2007, 2008, 2009 Free Software Foundation, Inc. ;; Author: Matthew Kennedy <mkennedy@gentoo.org> ;; Keywords: ;; This file is free software; you can redistribute it and/or modify ;; it under the terms of the GNU General Public License as published by ;; the Free Software Foundation; either version 2, or (at your option) ;; any later version. ;; This file 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 GNU Emacs; see the file COPYING. If not, write to the ;; Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, ;; Boston, MA 02110-1301 USA ;;; Commentary: ;; This code has been adapted from code found in emms-info-mp3info.el ;; written by Ulrik Jensen <terryp@daimi.au.dk> which contains the ;; following attribution: ;; This code has been adapted from code found in mp3player.el, written ;; by Jean-Philippe Theberge (jphiltheberge@videotron.ca), Mario ;; Domgoergen (kanaldrache@gmx.de) and Jorgen Schäfer ;; <forcer@forcix.cx> ;; To activate this method for getting info, use something like: ;; (require 'emms-info-metaflac) ;; (add-to-list 'emms-info-methods-list 'emms-info-metaflac) ;;; Code: (require 'emms-info) (defvar emms-info-metaflac-version "0.1 $Revision: 1.10 $" "EMMS info metaflac version string.") ;; $Id: emms-info-mp3info.el,v 1.10 2005/08/12 18:01:16 xwl Exp $ (defgroup emms-info-metaflac nil "An EMMS-info method for getting/setting FLAC tags, using the external metaflac program" :group 'emms-info) (defcustom emms-info-metaflac-program-name "metaflac" "*The name/path of the metaflac program." :type 'string :group 'emms-info-metaflac) (defcustom emms-info-metaflac-options '("--no-utf8-convert" "--show-tag=TITLE" "--show-tag=ARTIST" "--show-tag=ALBUM" "--show-tag=NOTE" "--show-tag=YEAR" "--show-tag=TRACKNUMBER" "--show-tag=DISCNUMBER" "--show-tag=GENRE") "The argument to pass to `emms-info-metaflac-program-name'." :type '(repeat string) :group 'emms-info-metaflac) (defun emms-info-metaflac (track) "Get the FLAC tag of file TRACK, using `emms-info-metaflac-program' and return an emms-info structure representing it." (when (and (eq 'file (emms-track-type track)) (string-match "\\.\\(flac\\|FLAC\\)\\'" (emms-track-name track))) (with-temp-buffer (when (zerop (apply 'call-process emms-info-metaflac-program-name nil t nil "--show-total-samples" "--show-sample-rate" (append emms-info-metaflac-options (list (emms-track-name track))))) (goto-char (point-min)) (emms-track-set track 'info-playing-time (/ (string-to-number (buffer-substring (point) (line-end-position))) (progn (forward-line 1) (string-to-number (buffer-substring (point) (line-end-position)))))) (forward-line 1) (while (looking-at "^\\([^=\n]+\\)=\\(.*\\)$") (let ((name (intern (concat "info-" (downcase (match-string 1))))) (value (match-string 2))) (when (> (length value) 0) (emms-track-set track name (if (eq name 'info-playing-time) (string-to-number value) value)))) (forward-line 1)))))) (provide 'emms-info-metaflac) ;;; emms-info-metaflac.el ends here �����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������emms-6.00/emms-info-mp3info.el����������������������������������������������������������������������0000664�0001750�0001750�00000007237�13746063641�014406� 0����������������������������������������������������������������������������������������������������ustar �yrk�����������������������������yrk��������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������;;; emms-info-mp3info.el --- Info-method for EMMS using mp3info ;; Copyright (C) 2003, 2004, 2005, 2006, 2007, 2008, ;; 2009 Free Software Foundation, Inc. ;; Authors: Ulrik Jensen <terryp@daimi.au.dk> ;; Jorgen Schäfer <forcer@forcix.cx> ;; Keywords: ;; 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, 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; see the file COPYING. If not, write to the ;; Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, ;; Boston, MA 02110-1301, USA. ;;; Commentary: ;; This code has been adapted from code found in mp3player.el, written ;; by Jean-Philippe Theberge (jphiltheberge@videotron.ca), Mario ;; Domgoergen (kanaldrache@gmx.de) and Jorgen Schäfer ;; <forcer@forcix.cx> ;; To activate this method for getting info, use something like: ;; (require 'emms-info-mp3info) ;; (add-to-list 'emms-info-functions 'emms-info-mp3info) ;;; Code: (require 'emms-info) (defvar emms-info-mp3info-version "0.2 $Revision: 1.10 $" "EMMS info mp3info version string.") ;; $Id: emms-info-mp3info.el,v 1.10 2005/08/12 18:01:16 xwl Exp $ (defgroup emms-info-mp3info nil "An EMMS-info method for getting/setting ID3v1 tags, using the external mp3info program" :group 'emms-info) (defcustom emms-info-mp3info-coding-system 'utf-8 "*Coding system used in the output of mp3info." :type 'coding-system :group 'emms-info-mp3info) (defcustom emms-info-mp3info-program-name "mp3info" "*The name/path of the mp3info tag program." :type 'string :group 'emms-info-mp3info) (defcustom emms-info-mp3find-arguments `("-p" ,(concat "info-artist=%a\\n" "info-title=%t\\n" "info-album=%l\\n" "info-tracknumber=%n\\n" "info-year=%y\\n" "info-genre=%g\\n" "info-note=%c\\n" "info-playing-time=%S\\n")) "The argument to pass to `emms-info-mp3info-program-name'. This should be a list of info-flag=value lines." :type '(repeat string) :group 'emms-info-mp3info) (defun emms-info-mp3info (track) "Add track information to TRACK. This is a useful element for `emms-info-functions'." (when (and (eq 'file (emms-track-type track)) (string-match "\\.[Mm][Pp]3\\'" (emms-track-name track))) (with-temp-buffer (when (zerop (apply (if (fboundp 'emms-i18n-call-process-simple) 'emms-i18n-call-process-simple 'call-process) emms-info-mp3info-program-name nil t nil (append emms-info-mp3find-arguments (list (emms-track-name track))))) (goto-char (point-min)) (while (looking-at "^\\([^=\n]+\\)=\\(.*\\)$") (let ((name (intern (match-string 1))) (value (match-string 2))) (when (> (length value) 0) (emms-track-set track name (if (eq name 'info-playing-time) (string-to-number value) value)))) (forward-line 1)))))) (provide 'emms-info-mp3info) ;;; emms-info-mp3info.el ends here �����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������emms-6.00/emms-info-ogginfo.el����������������������������������������������������������������������0000664�0001750�0001750�00000006130�13746063641�014452� 0����������������������������������������������������������������������������������������������������ustar �yrk�����������������������������yrk��������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������;;; emms-info-ogginfo.el --- Emms information from Ogg Vorbis files. ;; Copyright (C) 2005, 2006, 2007, 2008, 2009 Free Software Foundation, Inc. ;; Author: Jorgen Schaefer <forcer@forcix.cx> ;; Yoni Rabkin <yrk@gnu.org> ;; 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-ogginfo nil "An EMMS-info method for getting, using the external ogginfo program" :group 'emms-info) (defcustom emms-info-ogginfo-coding-system 'utf-8 "*Coding system used in the output of ogginfo." :type 'coding-system :group 'emms-info-ogginfo) (defcustom emms-info-ogginfo-program-name "ogginfo" "*The name/path of the ogginfo tag program." :type 'string :group 'emms-info-ogginfo) (defun emms-info-ogginfo (track) "Add track information to TRACK. This is a useful element for `emms-info-functions'." (when (and (eq 'file (emms-track-type track)) (string-match "\\.[Oo][Gg][Gg]\\'" (emms-track-name track))) (with-temp-buffer (call-process emms-info-ogginfo-program-name nil t nil (emms-track-name track)) ;; play time, emms-info-ogg.el [U. Jensen] (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-ogginfo) ;;; emms-info-ogginfo.el ends here ����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������emms-6.00/emms-info-opusinfo.el���������������������������������������������������������������������0000664�0001750�0001750�00000006141�13746063641�014666� 0����������������������������������������������������������������������������������������������������ustar �yrk�����������������������������yrk��������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������;;; emms-info-opusinfo.el --- Emms information from Ogg Opus files. ;; Copyright (C) 2018 Free Software Foundation, Inc. ;; Author: Pierre Neidhardt <mail@ambrevar.xyz> ;; 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 �������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������emms-6.00/emms-info-tinytag.el����������������������������������������������������������������������0000664�0001750�0001750�00000007435�13746063641�014512� 0����������������������������������������������������������������������������������������������������ustar �yrk�����������������������������yrk��������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������;;; emms-info-tinytag.el --- Info-method for EMMS using tinytag -*- lexical-binding: t; -*- ;; Copyright (C) 2020 Free Software Foundation, Inc. ;; Author: Fran Burstall <fran.burstall@gmail.com> ;; Keywords: multimedia ;; 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; see the file COPYING.. If not, see ;; <https://www.gnu.org/licenses/>. ;;; Commentary: ;; This code has been adapted from code found in emms-info-libtag.el, ;; written by Ulrik Jensen <terryp@daimi.au.dk> and Jorgen Schäfer ;; <forcer@forcix.cx>. ;; To activate this method for getting info, use: ;; (require 'emms-info-tinytag) ;; (add-to-list 'emms-info-functions 'emms-info-tinytag) ;; Note that you should remove emms-info-mp3info and emms-info-ogginfo ;; from the emms-info-functions list if you want to avoid ;; conflicts. For example, to set tinytag as your exclusive info ;; provider: ;; (setq emms-info-functions '(emms-info-tinytag)) ;; To use this provider, you need to install the tinytag python module ;; with something like: ;; pip install tinytag ;;; Code: (require 'emms-info) (require 'json) ;see below (defgroup emms-info-tinytag nil "Options for EMMS." :group 'emms-info) (defvar emms-info-tinytag-coding-system 'utf-8) ;is this used anywhere? (defcustom emms-info-tinytag-python-name "python" "Name of python we use." :type '(string) :group 'emms-info-tinytag) (defcustom emms-info-tinytag-known-extensions (regexp-opt '("mp3" "mp4" "m4a" "m4b" "ogg" "opus" "flac" "wma" "wav")) "Regexp of known extensions that `emms-info-tinytag' can handle. Case is irrelevant." :type '(string) :group 'emms-info-tinytag) (defvar emms-info-tinytag--info-fields '((info-album . album) (info-albumartist . albumartist) (info-artist . artist) (info-composer . composer) (info-year . year) (info-discnumber . disc) (info-genre . genre) (info-note . comment) (info-playing-time . duration) (info-title . title) (info-tracknumber . track)) "An alist mapping info-* fields to tinytag fields.") (defun emms-info-tinytag (track) "Set tags for TRACK using tinytag." (when (and (eq 'file (emms-track-type track)) (let ((case-fold-search t)) (string-match emms-info-tinytag-known-extensions (emms-track-name track)))) (with-temp-buffer (when (zerop (let ((coding-system-for-read 'utf-8)) (call-process emms-info-tinytag-python-name nil '(t nil) nil "-m" "tinytag" (emms-track-name track)))) (goto-char (point-min)) ;; tinytag can output json or [ct]sv. Sadly, in the latter ;; case, null values are unhelpfully represented by the string ;; "None" so we parse the json. (let ((track-info (json-read))) (dolist (field emms-info-tinytag--info-fields) (let ((name (car field)) (value (alist-get (cdr field) track-info))) (when (and value (or (numberp value) (> (length value) 0))) (emms-track-set track name (cond ((eq name 'info-playing-time) (round value)) ;; for m4a, disc or track is an int: issue raised upstream ((and (or (eq name 'info-discnumber) (eq name 'info-tracknumber)) (numberp value)) (number-to-string value)) (t value))))))))))) (provide 'emms-info-tinytag) ;;; emms-info-tinytag.el ends here �����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������emms-6.00/emms-info.el������������������������������������������������������������������������������0000664�0001750�0001750�00000011521�13746063641�013024� 0����������������������������������������������������������������������������������������������������ustar �yrk�����������������������������yrk��������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������;;; emms-info.el --- Retrieving track information ;; Copyright (C) 2005-2020 Free Software Foundation, Inc. ;; Author: Jorgen Schaefer <forcer@forcix.cx> ;; 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 EMMS module provides a way to add information for a track. ;; This can use an ID3 or OGG comment like syntax. ;; The code will add info symbols to the track. The following symbols ;; are defined: ;; info-artist - string naming the artist ;; info-composer - string naming the composer ;; info-performer - string naming the performer ;; info-title - string naming the title of the song ;; info-album - string naming the album ;; info-tracknumber - string(?) naming the track number ;; info-discnumber - string naming the disc number ;; info-year - string naming the year ;; info-note - string of free-form entry ;; info-genre - string naming the genre ;; info-playing-time - number giving the seconds of playtime ;;; Code: (require 'emms) (require 'emms-later-do) (defgroup emms-info nil "*Track information. ID3, OGG, etc." :group 'emms) (defcustom emms-info-auto-update t "*Non-nil when EMMS should update track information if the file changes. This will cause hard drive activity on track loading. If this is too annoying for you, set this variable to nil." :type 'boolean :group 'emms-info) (defcustom emms-info-asynchronously t "*Non-nil when track information should be loaded asynchronously. This requires `emms-later-do', which should come with EMMS." :type 'boolean :group 'emms-info) (defcustom emms-info-report-each-num-tracks 200 "*Non-zero will report progress information every number of tracks. The default is to display a message every 200 tracks. This variable is only used when adding tracks asynchronously." :type 'integer :group 'emms-info) (defcustom emms-info-functions nil "*Functions which add information to tracks. Each is called with a track as argument." :type 'hook :group 'emms-info) (defvar emms-info-asynchronous-tracks 0 "Number of tracks we're waiting for to be done.") (defun emms-info-initialize-track (track) "Initialize TRACK with emms-info information. This is a suitable value for `emms-track-initialize-functions'." (if (not emms-info-asynchronously) (emms-info-really-initialize-track track) (setq emms-info-asynchronous-tracks (1+ emms-info-asynchronous-tracks)) (emms-later-do 'emms-info-really-initialize-track track))) (defun emms-info-really-initialize-track (track) "Really initialize TRACK. Return t when the track got changed." (let ((file-mtime (when emms-info-auto-update (emms-info-track-file-mtime track))) (info-mtime (emms-track-get track 'info-mtime)) (name (emms-track-get track 'name))) ;; if the file's been modified or is new (when (or (not file-mtime) (not info-mtime) (emms-time-less-p info-mtime file-mtime)) (run-hook-with-args 'emms-info-functions track) ;; not set by info functions (when file-mtime (emms-track-set track 'info-mtime file-mtime)) (emms-track-updated track)) (when emms-info-asynchronously (setq emms-info-asynchronous-tracks (1- emms-info-asynchronous-tracks)) (if (zerop emms-info-asynchronous-tracks) (message "EMMS: All track information loaded.") (unless (zerop emms-info-report-each-num-tracks) (if (zerop (mod emms-info-asynchronous-tracks emms-info-report-each-num-tracks)) (message "EMMS: %d tracks to go.." emms-info-asynchronous-tracks))))))) (defun emms-info-track-file-mtime (track) "Return the mtime of the file of TRACK, if any. Return nil otherwise." (if (eq (emms-track-type track) 'file) (nth 5 (file-attributes (emms-track-name track))) nil)) (defun emms-info-track-description (track) "Return a description of TRACK." (let ((artist (emms-track-get track 'info-artist)) (title (emms-track-get track 'info-title))) (cond ((and artist title) (concat artist " - " title)) (title title) (t (emms-track-simple-description track))))) (provide 'emms-info) ;;; emms-info.el ends here �������������������������������������������������������������������������������������������������������������������������������������������������������������������������������emms-6.00/emms-last-played.el�����������������������������������������������������������������������0000664�0001750�0001750�00000011667�13746063641�014323� 0����������������������������������������������������������������������������������������������������ustar �yrk�����������������������������yrk��������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������;;; emms-last-played.el --- Support for last-played-time of a track ;; Copyright (C) 2006, 2007, 2008, 2009 Free Software Foundation, Inc. ;; Author: Lucas Bonnet <lucas@rincevent.net> ;; Keywords: emms, mp3, mpeg, multimedia ;; 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, 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; see the file COPYING. If not, write to the ;; Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, ;; Boston, MA 02110-1301, USA. ;;; Commentary: ;; Records when the track was last played. ;; Big portions of the time handling fuctions are copied from ;; gnus-util.el, and slightly adapted. ;;; Code: (require 'emms) (defvar emms-last-played-keep-count t "Specifies if EMMS should record the number of times you play a track. Set it to t if you want such a feature, and to nil if you don't.") (defvar emms-last-played-format-alist '(((emms-last-played-seconds-today) . "%k:%M") (604800 . "%a %k:%M") ;;that's one week ((emms-last-played-seconds-month) . "%a %d") ((emms-last-played-seconds-year) . "%b %d") (t . "%b %d '%y")) ;;this one is used when no ;;other does match "Specifies date format depending on when a track was last played. This is an alist of items (AGE . FORMAT). AGE can be a number (of seconds) or a Lisp expression evaluating to a number. When the age of the track is less than this number, then use `format-time-string' with the corresponding FORMAT for displaying the date of the track. If AGE is not a number or a Lisp expression evaluating to a non-number, then the corresponding FORMAT is used as a default value. Note that the list is processed from the beginning, so it should be sorted by ascending AGE. Also note that items following the first non-number AGE will be ignored. You can use the functions `emms-last-played-seconds-today', `emms-last-played-seconds-month' and `emms-last-played-seconds-year' in the AGE spec. They return the number of seconds passed since the start of today, of this month, of this year, respectively.") (defun emms-last-played-update-track (track) "Updates the last-played time of TRACK." (emms-track-set track 'last-played (current-time))) (defun emms-last-played-increment-count (track) "Increments the play-count property of TRACK. If non-existent, it is set to 1." (let ((play-count (emms-track-get track 'play-count))) (if play-count (emms-track-set track 'play-count (1+ play-count)) (emms-track-set track 'play-count 1)))) (defun emms-last-played-update-current () "Updates the current track." (emms-last-played-update-track (emms-playlist-current-selected-track)) (if emms-last-played-keep-count (emms-last-played-increment-count (emms-playlist-current-selected-track)))) (defun emms-last-played-seconds-today () "Return the number of seconds passed today." (let ((now (decode-time (current-time)))) (+ (car now) (* (car (cdr now)) 60) (* (car (nthcdr 2 now)) 3600)))) (defun emms-last-played-seconds-month () "Return the number of seconds passed this month." (let ((now (decode-time (current-time)))) (+ (car now) (* (car (cdr now)) 60) (* (car (nthcdr 2 now)) 3600) (* (- (car (nthcdr 3 now)) 1) 3600 24)))) (defun emms-last-played-seconds-year () "Return the number of seconds passed this year." (let ((now (decode-time (current-time))) (days (format-time-string "%j" (current-time)))) (+ (car now) (* (car (cdr now)) 60) (* (car (nthcdr 2 now)) 3600) (* (- (string-to-number days) 1) 3600 24)))) (defun emms-last-played-format-date (messy-date) "Format the messy-date according to emms-last-played-format-alist. Returns \" ? \" if there's bad input or if an other error occurs. Input should look like this: \"Sun, 14 Oct 2001 13:34:39 +0200\"." (condition-case () (let* ((messy-date (float-time messy-date)) (now (float-time (current-time))) ;;If we don't find something suitable we'll use this one (my-format "%b %d '%y")) (let* ((difference (- now messy-date)) (templist emms-last-played-format-alist) (top (eval (caar templist)))) (while (if (numberp top) (< top difference) (not top)) (progn (setq templist (cdr templist)) (setq top (eval (caar templist))))) (if (stringp (cdr (car templist))) (setq my-format (cdr (car templist))))) (format-time-string (eval my-format) (seconds-to-time messy-date))) (error "Never."))) (provide 'emms-last-played) ;;; emms-last-played.el ends here �������������������������������������������������������������������������emms-6.00/emms-later-do.el��������������������������������������������������������������������������0000664�0001750�0001750�00000006415�13746063641�013606� 0����������������������������������������������������������������������������������������������������ustar �yrk�����������������������������yrk��������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������;;; emms-later-do.el --- execute lisp code ... later ;; Copyright (C) 2004, 2005, 2006, 2007, 2008, ;; 2009, 2018 Free Software Foundation, Inc. ;; Author: Jorgen Schaefer <forcer@forcix.cx> ;;; This program is free software; you can redistribute it and/or ;;; modify it under the terms of the GNU General Public License ;;; as published by the Free Software Foundation; either version 3 ;;; of the License, or (at your option) any later version. ;;; This program is distributed in the hope that it will be useful, ;;; but WITHOUT ANY WARRANTY; without even the implied warranty of ;;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ;;; GNU General Public License for more details. ;;; You should have received a copy of the GNU General Public License ;;; along with this program; if not, write to the Free Software ;;; Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA ;;; 02110-1301 USA ;;; Commentary ;; This file will execute lisp code ``later on''. This way it is ;; possible to work while elisp does some longer calculations, if you ;; can convert those calculations into a sequence of function calls. ;; 2020-09-22: Name changed from later-do to emms-later-do in order to ;; avoid polluting the namespace. ;;; Code: (defvar emms-later-do-version "0.2emms4 (2018-04-07)" "Version string of emms-later-do.") (defgroup emms-later-do nil "*Running functions ... later!" :prefix "emms-later-do-" :group 'development) (defcustom emms-later-do-interval 0.5 "How many seconds to wait between running events." :group 'emms-later-do :type 'number) (defcustom emms-later-do-batch 20 "How many functions to process before waiting `emms-later-do-interval'. The functions are processed from `emms-later-do-list'. Must be 1 or greater. Too high a value might make Emacs slower while the list is being processed." :group 'emms-later-do :type 'number) (defvar emms-later-do-list nil "A list of functions to be called later on.") (defvar emms-later-do-timer nil "The timer that emms-later-do uses.") (defun emms-later-do (function &rest args) "Apply FUNCTION to ARGS later on. This is an unspecified amount of time after this call, and definitely not while lisp is still executing. Code added using `emms-later-do' is guaranteed to be executed in the sequence it was added." (setq emms-later-do-list (nconc emms-later-do-list (list (cons function args)))) (unless emms-later-do-timer (setq emms-later-do-timer (run-with-timer emms-later-do-interval nil 'emms-later-do-timer)))) (defun emms-later-do-timer () "Run the next element in `emms-later-do-list', or do nothing if it's empty." (if (null emms-later-do-list) (setq emms-later-do-timer nil) (let (res) (unwind-protect (dotimes (b (min emms-later-do-batch (length emms-later-do-list)) res) (let ((fun (caar emms-later-do-list)) (args (cdar emms-later-do-list))) (setq emms-later-do-list (cdr emms-later-do-list)) (setq res (apply fun args))))) (setq emms-later-do-timer (run-with-timer emms-later-do-interval nil 'emms-later-do-timer))))) (provide 'emms-later-do) ;;; emms-later-do.el ends here ���������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������emms-6.00/emms-librefm-scrobbler.el�����������������������������������������������������������������0000664�0001750�0001750�00000026532�13746063641�015474� 0����������������������������������������������������������������������������������������������������ustar �yrk�����������������������������yrk��������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������;;; emms-librefm-scrobbler.el --- Libre.FM Scrobbing API ;; Copyright (C) 2014 Free Software Foundation, Inc. ;; Author: Yoni Rabkin <yrk@gnu.org> ;; Keywords: emms, libre.fm, GNU FM ;; 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, 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; see the file COPYING. If not, write to the Free ;; Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, ;; MA 02110-1301, USA. ;;; Commentary: ;; To use libre.fm you need to add username and password to ;; ~/.authinfo.gpg or an equivalent file understood by auth-source. ;; To enable scrobbling call (emms-librefm-scrobbler-enable). ;;; Code: (require 'emms-playing-time) (require 'auth-source) (defvar emms-librefm-scrobbler-handshake-url "turtle.libre.fm" "Endpoint for client handshake.") (defvar emms-librefm-scrobbler-method "https" "Transfer method.") (defvar emms-librefm-scrobbler-username nil "Libre.fm username. Note that the preferred way of authenticating is using authinfo and only setting `emms-librefm-scrobbler-handshake-url'. See the manual for details.") (defvar emms-librefm-scrobbler-password nil "Libre.fm user password. Note that the preferred way of authenticating is using authinfo. See also `emms-librefm-scrobbler-username'.") (defvar emms-librefm-scrobbler-debug "" "Debugging variable to store communication.") (defvar emms-librefm-scrobbler-session-id nil "Session ID for Libre.fm.") (defvar emms-librefm-scrobbler-now-playing-url "" "URL for getting the track playing.") (defvar emms-librefm-scrobbler-submission-url "" "URL for submissions.") (defvar emms-librefm-scrobbler-track-play-start-timestamp nil "Time when a track started playing.") (defvar emms-librefm-scrobbler-display-submissions t "Whether to display a user message on every submission.") ;;; ------------------------------------------------------------------ ;;; authenticate ;;; ------------------------------------------------------------------ (defun emms-librefm-scrobbler--get-auth-detail (token) "Return TOKEN from auth-source. TOKEN is :user of :secret." ;; TODO: Maybe we should enable :create t here. But it could be ;; kind of annoying as it makes a pop-up when no name is present. (plist-get (car (auth-source-search :host (list emms-librefm-scrobbler-handshake-url "libre.fm") :user (unless (equal emms-librefm-scrobbler-username "") emms-librefm-scrobbler-username) :max 1 :require '(:user :secret))) token)) (defun emms-librefm-scrobbler--username () "Return username for libre.fm." (or (emms-librefm-scrobbler--get-auth-detail :user) emms-librefm-scrobbler-username)) (defun emms-librefm-scrobbler--password () "Return password for libre.fm." (let ((token (emms-librefm-scrobbler--get-auth-detail :secret))) (cond ((functionp token) (funcall token)) ((characterp token) token) (t emms-librefm-scrobbler-password)))) ;;; ------------------------------------------------------------------ ;;; handshake ;;; ------------------------------------------------------------------ (defun emms-librefm-scrobbler-handshake-string (url username password) "Return the client handshake string." (when (= 0 (length url)) (error "bad url")) (when (= 0 (length username)) (error "bad username")) (when (= 0 (length password)) (error "bad password")) (let ((timestamp (format-time-string "%s"))) (concat emms-librefm-scrobbler-method "://" url "/?" "hs=true" "&" "p=1.2" "&" "c=emm" "&" "v=1.0" "&" "u=" (url-encode-url username) "&" "t=" timestamp "&" "a=" (md5 (concat (md5 password) timestamp))))) (defun emms-librefm-scrobbler-handshake-call (url username password) "Perform client handshake and return a response in a buffer." (let ((url-request-method "POST")) (let ((response (url-retrieve-synchronously (emms-librefm-scrobbler-handshake-string url username password)))) (setq emms-librefm-scrobbler-debug (with-current-buffer response (buffer-substring-no-properties (point-min) (point-max)))) response))) (defun emms-librefm-scrobbler-handle-handshake-response (resbuf) "Handle the client handshake server response." (when (not (bufferp resbuf)) (error "response not a buffer")) (with-current-buffer resbuf (goto-char (point-min)) (when (not (re-search-forward "^.*200 OK$" (point-at-eol) t)) (error "bad HTTP server response")) ;; go to the start of the FM response (when (not (re-search-forward "\n\n" (point-max) t)) (error "bad FM server response")) (let ((status (buffer-substring (point-at-bol) (point-at-eol)))) (when (not (string= status "OK")) (error "FM server returned: %s" status)) (let (session-id now-playing-url submission-url) (forward-line 1) (setq session-id (buffer-substring (point-at-bol) (point-at-eol))) (forward-line 1) (setq now-playing-url (buffer-substring (point-at-bol) (point-at-eol))) (forward-line 1) (setq submission-url (buffer-substring (point-at-bol) (point-at-eol))) (when (or (= 0 (length session-id)) (= 0 (length now-playing-url)) (= 0 (length submission-url))) (error "couldn't parse FM server response")) (setq emms-librefm-scrobbler-session-id session-id emms-librefm-scrobbler-now-playing-url now-playing-url emms-librefm-scrobbler-submission-url submission-url) (message "handshake successful"))))) (defun emms-librefm-scrobbler-handshake () "Perform client handshake call and handle response." (emms-librefm-scrobbler-handle-handshake-response (emms-librefm-scrobbler-handshake-call emms-librefm-scrobbler-handshake-url (emms-librefm-scrobbler--username) (emms-librefm-scrobbler--password)))) ;;; ------------------------------------------------------------------ ;;; submission ;;; ------------------------------------------------------------------ (defun emms-librefm-scrobbler-make-query (track rating) "Format the url parameters for scrobbling." (setq rating (cond ((equal 'love rating) "L") ((equal 'ban rating) "B") ((equal 'skip rating) "S") (t ""))) (let ((artist (emms-track-get track 'info-artist)) (title (emms-track-get track 'info-title)) (album (or (emms-track-get track 'info-album) "")) (track-number (emms-track-get track 'info-tracknumber)) (musicbrainz-id "") (track-length (number-to-string (or (emms-track-get track 'info-playing-time) 0)))) (if (and artist title) (concat "s=" emms-librefm-scrobbler-session-id "&a[0]=" (url-encode-url artist) "&t[0]=" (url-encode-url title) "&i[0]=" (url-encode-url (or emms-librefm-scrobbler-track-play-start-timestamp (format-time-string "%s"))) "&o[0]=" "P" "&r[0]=" (url-encode-url rating) "&l[0]=" track-length "&b[0]=" (url-encode-url album) "&n[0]=" track-number "&m[0]=" musicbrainz-id) (error "Track title and artist must be known.")))) ;;; ------------------------------------------------------------------ ;;; asynchronous submission ;;; ------------------------------------------------------------------ (defun emms-librefm-scrobbler-get-response-status () "Check the HTTP header and return the body." (let ((ok200 "HTTP/1.1 200 OK")) (if (< (point-max) 1) (error "No response from submission server")) (if (not (string= ok200 (buffer-substring-no-properties (point-min) 16))) (error "submission server not responding correctly")) (goto-char (point-min)) (re-search-forward "\n\n") (buffer-substring-no-properties (point-at-bol) (point-at-eol)))) (defun emms-librefm-scrobbler-make-async-submission-call (track rating) "Make asynchronous submission call." (let ((flarb (emms-librefm-scrobbler-make-query track rating))) (let* ((url-request-method "POST") (url-request-data flarb) (url-request-extra-headers `(("Content-type" . "application/x-www-form-urlencoded")))) (url-retrieve emms-librefm-scrobbler-submission-url #'emms-librefm-scrobbler-async-submission-callback (list (cons track rating)))))) (defun emms-librefm-scrobbler-async-submission-callback (status &optional cbargs) "Pass response of asynchronous submission call to handler." (let ((response (emms-librefm-scrobbler-get-response-status))) ;; From the API docs: This indicates that the ;; submission request was accepted for processing. It ;; does not mean that the submission was valid, but ;; only that the authentication and the form of the ;; submission was validated. (let ((track (car cbargs))) (cond ((string= response "OK") (when emms-librefm-scrobbler-display-submissions (message "Libre.fm: Submitted %s" (emms-track-get track 'info-title)))) ((string= response "BADSESSION") (emms-librefm-scrobbler-handshake) (emms-librefm-scrobbler-make-async-submission-call (car cbargs) (cdr cbargs))) (t (error "unhandled submission failure")))))) ;;; ------------------------------------------------------------------ ;;; hooks ;;; ------------------------------------------------------------------ (defun emms-librefm-scrobbler-start-hook () (setq emms-librefm-scrobbler-track-play-start-timestamp (format-time-string "%s"))) (defun emms-librefm-scrobbler-stop-hook () "Submit the track to libre.fm if it has been played for 240 seconds or half the length of the track." (let ((current-track (emms-playlist-current-selected-track))) (let ((track-length (emms-track-get current-track 'info-playing-time))) (when (and track-length ;; only submit files (eq (emms-track-type current-track) 'file)) (when (and ;; track must be longer than 30 secs (> track-length 30) ;; track must be played for more than 240 secs or ;; half the tracks length, whichever comes first. (> emms-playing-time (min 240 (/ track-length 2)))) (emms-librefm-scrobbler-make-async-submission-call current-track nil)))))) (defun emms-librefm-scrobbler-enable () "Enable the scrobbler and submit played tracks." (interactive) (when (not emms-librefm-scrobbler-session-id) (emms-librefm-scrobbler-handshake)) (add-hook 'emms-player-started-hook 'emms-librefm-scrobbler-start-hook t) (add-hook 'emms-player-stopped-hook 'emms-librefm-scrobbler-stop-hook) (add-hook 'emms-player-finished-hook 'emms-librefm-scrobbler-stop-hook)) (defun emms-librefm-scrobbler-disable () "Disable the scrobbler and don't submit played tracks." (interactive) (setq emms-librefm-scrobbler-session-id nil) (remove-hook 'emms-player-started-hook 'emms-librefm-scrobbler-start-hook) (remove-hook 'emms-player-stopped-hook 'emms-librefm-scrobbler-stop-hook) (remove-hook 'emms-player-finished-hook 'emms-librefm-scrobbler-stop-hook)) (provide 'emms-librefm-scrobbler) ;;; emms-librefm-scrobbler.el ends here ����������������������������������������������������������������������������������������������������������������������������������������������������������������������emms-6.00/emms-librefm-stream.el��������������������������������������������������������������������0000664�0001750�0001750�00000030644�13746063641�015011� 0����������������������������������������������������������������������������������������������������ustar �yrk�����������������������������yrk��������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������;;; emms-librefm-stream.el --- Libre.FM streaming ;; Copyright (C) 2014 Free Software Foundation, Inc. ;; Author: Yoni Rabkin <yrk@gnu.org> ;; Keywords: emms, libre.fm, GNU FM ;; 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, 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; see the file COPYING. If not, write to the Free ;; Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, ;; MA 02110-1301, USA. ;;; Code: (require 'xml) (require 'emms-playlist-mode) (require 'emms-librefm-scrobbler) (defvar emms-librefm-stream-host-url "alpha.libre.fm" "URL for the streaming host") (defvar emms-librefm-stream-host-base-path "" "URL for the streaming host base path") (defvar emms-librefm-stream-session-id "" "Session ID for radio.") (defvar emms-librefm-stream-debug "" "Temporary debug information.") (defvar emms-librefm-stream-station-name "" "Last station name tuned to.") (defvar emms-librefm-stream-emms-tracklist "" "List of tracks for streaming.") (defvar emms-librefm-stream-playlist-buffer-name "*Emms GNU FM*" "Name for non-interactive Emms GNU FM buffer.") (defvar emms-librefm-stream-playlist-buffer nil "Non-interactive Emms GNU FM buffer.") (defvar emms-librefm-stream-connect-method "https://" "Method of connecting to server.") ;;; ------------------------------------------------------------------ ;;; HTTP ;;; ------------------------------------------------------------------ (defun emms-librefm-stream-assert-http () "Assert a sane HTTP response from the server. This function must be called inside the response buffer. Leaves point after the HTTP headers." (goto-char (point-min)) (when (not (re-search-forward "^.*200 OK$" (point-at-eol) t)) (error "bad HTTP server response")) ;; go to the start of the FM response (when (not (re-search-forward "\n\n" (point-max) t)) (error "bad FM server response"))) ;;; ------------------------------------------------------------------ ;;; radio handshake ;;; ------------------------------------------------------------------ (defun emms-librefm-stream-tune-handshake-string () "Create the tune handshake string." (when (not emms-librefm-scrobbler-username) (error "null username")) (when (not emms-librefm-scrobbler-password) (error "null password")) (let ((url (concat emms-librefm-stream-connect-method emms-librefm-stream-host-url "/radio/handshake.php?" "version=1.3.0.58" "&" "platform=linux" "&" "username=" (url-encode-url emms-librefm-scrobbler-username) "&" "passwordmd5=" (md5 emms-librefm-scrobbler-password) "&" "language=en"))) url)) (defun emms-librefm-stream-tune-handshake-call () "Make the tune handshake call." (let ((url-request-method "POST")) (let ((response (url-retrieve-synchronously (emms-librefm-stream-tune-handshake-string)))) (setq emms-librefm-stream-debug (with-current-buffer response (buffer-substring-no-properties (point-min) (point-max)))) response))) (defun emms-librefm-stream-handle-tune-handshake-response (resbuf) "Handle the tune handshake server response." (when (not (bufferp resbuf)) (error "response not a buffer")) (with-current-buffer resbuf (emms-librefm-stream-assert-http) (let (radio-session-id base-url base-path (start (point))) (if (re-search-forward "^session=\\(.*\\)$" (point-max) t) (setq radio-session-id (match-string-no-properties 1)) (error "no radio session ID from server")) (goto-char start) (if (re-search-forward "^base_url=\\(.*\\)$" (point-max) t) (setq base-url (match-string-no-properties 1)) (error "no base url from server")) (goto-char start) (if (re-search-forward "^base_path=\\(.*\\)$" (point-max) t) (setq base-path (match-string-no-properties 1)) (error "no base path from server")) (setq emms-librefm-stream-session-id radio-session-id emms-librefm-stream-host-url base-url emms-librefm-stream-host-base-path base-path)) (message "radio handshake successful"))) (defun emms-librefm-stream-tune-handshake () "Make and handle the tune handshake." (emms-librefm-stream-handle-tune-handshake-response (emms-librefm-stream-tune-handshake-call))) ;;; ------------------------------------------------------------------ ;;; tuning ;;; ------------------------------------------------------------------ (defun emms-librefm-stream-tune-string (session-id station) "Create the tune string." (when (not session-id) (error "null session id")) (when (not station) (error "null station")) (let ((url (concat emms-librefm-stream-connect-method emms-librefm-stream-host-url emms-librefm-stream-host-base-path "/adjust.php?" "session=" session-id "&" "url=" (url-encode-url station)))) url)) (defun emms-librefm-stream-tune-call (session-id station) "Make the tune call." (let ((url-request-method "POST")) (let ((response (url-retrieve-synchronously (emms-librefm-stream-tune-string session-id station)))) (setq emms-librefm-stream-debug (with-current-buffer response (buffer-substring-no-properties (point-min) (point-max)))) response))) (defun emms-librefm-stream-handle-tune-response (resbuf) "Handle the tune server response." (when (not (bufferp resbuf)) (error "response not a buffer")) (with-current-buffer resbuf (emms-librefm-stream-assert-http) (let ((status (buffer-substring (point-at-bol) (point-at-eol)))) (let (response url stationname (start (point))) (if (re-search-forward "^response=\\(.*\\)$" (point-max) t) (setq response (match-string-no-properties 1)) (error "no response status code")) (when (not (string= response "OK")) (error "tune response not OK")) (goto-char start) (if (re-search-forward "^url=\\(.*\\)$" (point-max) t) (setq url (match-string-no-properties 1)) (error "no url from server")) (goto-char start) (if (re-search-forward "^stationname=\\(.*\\)$" (point-max) t) (setq stationname (match-string-no-properties 1)) (error "no stationname from server")) (setq emms-librefm-stream-station-name stationname) (message "successfully tuned to: %s" stationname))))) (defun emms-librefm-stream-tune (station) "Make and handle tune call." (emms-librefm-stream-handle-tune-response (emms-librefm-stream-tune-call emms-librefm-stream-session-id station))) ;;; ------------------------------------------------------------------ ;;; radio.getPlaylist ;;; ------------------------------------------------------------------ (defun emms-librefm-stream-getplaylist-string (radio-session-id) "Create the getplaylist string." (when (not radio-session-id) (error "null radio session id")) (let ((url (concat emms-librefm-stream-connect-method emms-librefm-stream-host-url emms-librefm-stream-host-base-path "/xspf.php?" "sk=" radio-session-id "&" "discovery=0" "&" "desktop=1.3.0.58"))) url)) (defun emms-librefm-stream-getplaylist-call (session-id) "Make the getplaylist call." (let ((url-request-method "POST")) (let ((response (url-retrieve-synchronously (emms-librefm-stream-getplaylist-string session-id)))) (setq emms-librefm-stream-debug (with-current-buffer response (buffer-substring-no-properties (point-min) (point-max)))) response))) (defun emms-librefm-stream-handle-getplaylist-response (resbuf) "Handle the getplaylist server response." (when (not (bufferp resbuf)) (error "response not a buffer")) (with-current-buffer resbuf (emms-librefm-stream-assert-http) (xml-parse-region (point) (point-max)))) (defun emms-librefm-stream-getplaylist () "Make and handle radio.getPlaylist." (emms-librefm-stream-handle-getplaylist-response (emms-librefm-stream-getplaylist-call emms-librefm-stream-session-id))) ;;; ------------------------------------------------------------------ ;;; XSPF ;;; ------------------------------------------------------------------ (defun emms-librefm-stream-xspf-find (tag data) "Return the tracklist portion of PLAYLIST or nil." (let ((tree (copy-tree data)) result) (while (and tree (not result)) (let ((this (car tree))) (when (and (listp this) (eq (car this) tag)) (setq result this))) (setq tree (cdr tree))) result)) (defun emms-librefm-stream-xspf-tracklist (playlist) "Return the tracklist portion of PLAYLIST or nil." (emms-librefm-stream-xspf-find 'trackList (car playlist))) (defun emms-librefm-stream-xspf-get (tag track) "Return the data associated with TAG in TRACK." (nth 2 (emms-librefm-stream-xspf-find tag track))) (defun emms-librefm-stream-xspf-convert-track (track) "Convert TRACK to an Emms track." (let ((location (emms-librefm-stream-xspf-get 'location track)) (title (emms-librefm-stream-xspf-get 'title track)) (album (emms-librefm-stream-xspf-get 'album track)) (creator (emms-librefm-stream-xspf-get 'creator track)) (duration (emms-librefm-stream-xspf-get 'duration track)) (image (emms-librefm-stream-xspf-get 'image track))) (let ((emms-track (emms-dictionary '*track*))) (emms-track-set emms-track 'name location) (emms-track-set emms-track 'info-artist creator) (emms-track-set emms-track 'info-title title) (emms-track-set emms-track 'info-album album) (emms-track-set emms-track 'info-playing-time (/ (string-to-number duration) 1000)) (emms-track-set emms-track 'type 'url) emms-track))) (defun emms-librefm-stream-xspf-convert-tracklist (tracklist) "Convert TRACKLIST to a list of Emms tracks." (let (tracks) (mapc #'(lambda (e) (when (and (listp e) (eq 'track (car e))) (setq tracks (append tracks `(,(emms-librefm-stream-xspf-convert-track e)))))) tracklist) tracks)) ;;; ------------------------------------------------------------------ ;;; stream ;;; ------------------------------------------------------------------ (defun emms-librefm-stream-set-librefm-playlist-buffer () "Setup the GNU FM buffer and make it `emms-playlist-buffer'." (when (not (buffer-live-p emms-librefm-stream-playlist-buffer)) (setq emms-librefm-stream-playlist-buffer (emms-playlist-new emms-librefm-stream-playlist-buffer-name))) (setq emms-playlist-buffer emms-librefm-stream-playlist-buffer)) (defun emms-librefm-stream-queue () "Queue streaming tracks." (let ((tracklist (emms-librefm-stream-xspf-tracklist (emms-librefm-stream-getplaylist)))) (when (not tracklist) (setq emms-librefm-stream-emms-tracklist nil) (error "could not find tracklist")) (setq emms-librefm-stream-emms-tracklist (emms-librefm-stream-xspf-convert-tracklist tracklist)) (emms-librefm-stream-set-librefm-playlist-buffer) (with-current-emms-playlist (goto-char (point-max)) (save-excursion (mapc #'(lambda (track) (emms-playlist-insert-track track)) emms-librefm-stream-emms-tracklist))))) (defun emms-librefm-stream-queue-loader () "Queue more streaming music if needed." (with-current-emms-playlist (goto-char (if emms-playlist-mode-selected-overlay (overlay-start emms-playlist-mode-selected-overlay) (point-min))) (when (and (eq (current-buffer) emms-librefm-stream-playlist-buffer) (not (next-single-property-change (point-at-eol) 'emms-track))) (emms-librefm-stream-queue)))) (defun emms-librefm-stream (station) "Stream STATION from a GNU FM server." (interactive "sEnter station URL: ") (when (not (stringp station)) (error "bad argument")) (add-hook 'emms-player-finished-hook 'emms-librefm-stream-queue-loader) (emms-librefm-stream-tune-handshake) (emms-librefm-stream-tune station) (message "tuned to %s, getting playlist..." emms-librefm-stream-station-name) (emms-librefm-stream-queue) (with-current-emms-playlist (emms-playlist-mode-play-current-track))) (provide 'emms-librefm-stream) ;;; emms-librefm-stream.el ends here ��������������������������������������������������������������������������������������������emms-6.00/emms-lyrics.el����������������������������������������������������������������������������0000664�0001750�0001750�00000050121�13746063641�013375� 0����������������������������������������������������������������������������������������������������ustar �yrk�����������������������������yrk��������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������;;; emms-lyrics.el --- Display lyrics synchronically ;; Copyright (C) 2005, 2006, 2007, 2008, 2009, 2010, 2013 Free Software Foundation, Inc. ;; Author: William Xu <william.xwl@gmail.com> ;; Keywords: emms music lyrics ;; 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, 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 package enables you to play music files and display lyrics ;; synchronically! :-) Plus, it provides a `emms-lyrics-mode' for ;; making lyric files. ;; Put this file into your load-path and the following into your ;; ~/.emacs: ;; (require 'emms-lyrics) ;; ;; Then either `M-x emms-lyrics-enable' or add (emms-lyrics 1) in ;; your .emacs to enable. ;;; TODO: ;; 1. Maybe the lyric setup should run before `emms-start'. ;; 2. Give a user a chance to choose when finding out multiple lyrics. ;; 3. Search .lrc format lyrics from internet ? ;;; Code: (require 'emms) (require 'emms-player-simple) (require 'emms-source-file) (require 'time-date) (require 'emms-url) (require 'emms-compat) ;;; User Customization (defgroup emms-lyrics nil "Lyrics module for EMMS." :group 'emms) (defcustom emms-lyrics-display-on-modeline t "If non-nil, display lyrics on mode line." :type 'boolean :group 'emms-lyrics) (defcustom emms-lyrics-display-on-minibuffer nil "If non-nil, display lyrics on minibuffer." :type 'boolean :group 'emms-lyrics) (defcustom emms-lyrics-display-buffer nil "Non-nil will create deciated `emms-lyrics-buffer' to display lyrics." :type 'boolean :group 'emms-lyrics) (defcustom emms-lyrics-dir "~/music/lyrics" "Local lyrics repository. `emms-lyrics-find-lyric' will look for lyrics in current directory(i.e., same as the music file) and this directory." :type 'string :group 'emms-lyrics) (defcustom emms-lyrics-display-format " %s " "Format for displaying lyrics." :type 'string :group 'emms-lyrics) (defcustom emms-lyrics-coding-system nil "Coding system for reading lyrics files. If all your lyrics use the same coding system, you can set this variable to that value; else you'd better leave it to nil, and rely on `prefer-coding-system', `file-coding-system-alist' or \(info \"(emacs)File Variables\"), sorted by priority increasingly." :type 'coding-system :group 'emms-lyrics) (defcustom emms-lyrics-mode-hook nil "Normal hook run after entering Emms Lyric mode." :type 'hook :group 'emms-lyrics) (defcustom emms-lyrics-find-lyric-function 'emms-lyrics-find-lyric "Function for finding lyric files." :type 'symbol :group 'emms-lyrics) (defcustom emms-lyrics-scroll-p t "Non-nil value will enable lyrics scrolling on mode line. Note: Even if this is set to t, it also depends on `emms-lyrics-display-on-modeline' to be t." :type 'boolean :group 'emms-lyrics) (defcustom emms-lyrics-scroll-timer-interval 0.4 "Interval between scroller timers. The shorter, the faster." :type 'number :group 'emms-lyrics) ;;; User Interfaces (defvar emms-lyrics-display-p t "If non-nil, will diplay lyrics.") (defvar emms-lyrics-mode-line-string "" "Current lyric.") (defvar emms-lyrics-buffer nil "Buffer to show lyrics.") (defvar emms-lyrics-chinese-url "http://mp3.baidu.com/m?f=ms&rn=10&tn=baidump3lyric&ct=150994944&word=%s&lm=-1" "URL used to find Chinese lyrics. Should contain one %s which is replaced with the filename.") (defvar emms-lyrics-latin-url "http://lyrics.wikia.com/%s%s" "URL used to find Latin lyrics. Should contain two %s-expressions. The first is replaced with the artist and second with the title.") ;;;###autoload (defun emms-lyrics-enable () "Enable displaying emms lyrics." (interactive) (emms-lyrics 1) (message "emms lyrics enabled.")) ;;;###autoload (defun emms-lyrics-disable () "Disable displaying emms lyrics." (interactive) (emms-lyrics -1) (message "EMMS lyrics disabled")) ;;;###autoload (defun emms-lyrics-toggle () "Toggle displaying emms lyrics." (interactive) (if emms-lyrics-display-p (emms-lyrics-disable) (emms-lyrics-enable))) (defun emms-lyrics-toggle-display-on-minibuffer () "Toggle display lyrics on minibbufer." (interactive) (if emms-lyrics-display-on-minibuffer (progn (setq emms-lyrics-display-on-minibuffer nil) (message "Disable lyrics on minibufer")) (setq emms-lyrics-display-on-minibuffer t) (message "Enable lyrics on minibufer"))) (defun emms-lyrics-toggle-display-on-modeline () "Toggle display lyrics on mode line." (interactive) (if emms-lyrics-display-on-modeline (progn (setq emms-lyrics-display-on-modeline nil emms-lyrics-mode-line-string "") (message "Disable lyrics on mode line")) (setq emms-lyrics-display-on-modeline t) (message "Enable lyrics on mode line"))) (defun emms-lyrics-toggle-display-buffer () "Toggle showing/hiding `emms-lyrics-buffer'." (interactive) (let ((w (get-buffer-window emms-lyrics-buffer))) (if w (delete-window w) (save-selected-window (pop-to-buffer emms-lyrics-buffer) (set-window-dedicated-p w t))))) (defun emms-lyrics (arg) "Turn on emms lyrics display if ARG is positive, off otherwise." (interactive "p") (if (and arg (> arg 0)) (progn (setq emms-lyrics-display-p t) (add-hook 'emms-player-started-hook 'emms-lyrics-start) (add-hook 'emms-player-stopped-hook 'emms-lyrics-stop) (add-hook 'emms-player-finished-hook 'emms-lyrics-stop) (add-hook 'emms-player-paused-hook 'emms-lyrics-pause) (add-hook 'emms-player-seeked-functions 'emms-lyrics-seek) (add-hook 'emms-player-time-set-functions 'emms-lyrics-sync)) (emms-lyrics-stop) (setq emms-lyrics-display-p nil) (emms-lyrics-restore-mode-line) (remove-hook 'emms-player-started-hook 'emms-lyrics-start) (remove-hook 'emms-player-stopped-hook 'emms-lyrics-stop) (remove-hook 'emms-player-finished-hook 'emms-lyrics-stop) (remove-hook 'emms-player-paused-hook 'emms-lyrics-pause) (remove-hook 'emms-player-seeked-functions 'emms-lyrics-seek) (remove-hook 'emms-player-time-set-functions 'emms-lyrics-sync))) (defun emms-lyrics-visit-lyric () "Visit playing track's lyric file. If we can't find it from local disk, then search it from internet." (interactive) (let* ((track (emms-playlist-current-selected-track)) (name (emms-track-get track 'name)) (lrc (funcall emms-lyrics-find-lyric-function (emms-replace-regexp-in-string (concat "\\." (file-name-extension name) "\\'") ".lrc" (file-name-nondirectory name))))) (if (and lrc (file-exists-p lrc) (not (string= lrc ""))) (find-file lrc) (message "Lyric file does not exist on file-system. Searching online...") (let* ((title (or (emms-track-get track 'info-title) (file-name-sans-extension (file-name-nondirectory name)))) (artist (when (emms-track-get track 'info-title) (emms-track-get track 'info-artist))) (url (cond ((string-match "\\cc" title) ; Chinese lyrics. ;; Since tag info might be encoded using various coding ;; systems, we'd better fall back on filename. (format emms-lyrics-chinese-url (emms-url-quote-plus (encode-coding-string name 'gb2312)))) (t ; English lyrics.g (format emms-lyrics-latin-url (if artist (concat (emms-url-quote-underscore artist) ":") "") (emms-url-quote-underscore title)))))) (if (fboundp 'eww) (progn (require 'eww) (let ((readable-hook (when (fboundp 'eww-readable) (add-hook 'eww-after-render-hook 'eww-readable)))) (eww url) (when readable-hook (remove-hook 'eww-after-render-hook 'eww-readable)))) (browse-url url)) (message "Lyric file does not exist on file-system. Searching online..."))))) ;;; EMMS Lyrics (defvar emms-lyrics-alist nil "a list of the form: '((time0 . lyric0) (time1 . lyric1)...)). In short, at time-i, display lyric-i.") (defvar emms-lyrics-timers nil "timers for displaying lyric.") (defvar emms-lyrics-start-time nil "emms lyric start time.") (defvar emms-lyrics-pause-time nil "emms lyric pause time.") (defvar emms-lyrics-elapsed-time 0 "How long time has emms lyric played.") (defvar emms-lyrics-scroll-timers nil "Lyrics scroller timers.") (defun emms-lyrics-read-file (file &optional catchup) "Read a lyric file(LRC format). Optional CATCHUP is for recognizing `emms-lyrics-catchup'. FILE should end up with \".lrc\", its content looks like one of the following: [1:39]I love you, Emacs! [00:39]I love you, Emacs! [00:39.67]I love you, Emacs! FILE should be under the same directory as the music file, or under `emms-lyrics-dir'." (or catchup (setq file (funcall emms-lyrics-find-lyric-function file))) (when (and file (file-exists-p file)) (with-temp-buffer (let ((coding-system-for-read emms-lyrics-coding-system)) (emms-insert-file-contents file) (while (search-forward-regexp "\\[[0-9:.]+\\].*" nil t) (let ((lyric-string (match-string 0)) (time 0) (lyric "")) (setq lyric (emms-replace-regexp-in-string ".*\\]" "" lyric-string)) (while (string-match "\\[[0-9:.]+\\]" lyric-string) (let* ((time-string (match-string 0 lyric-string)) (semi-pos (string-match ":" time-string))) (setq time (+ (* (string-to-number (substring time-string 1 semi-pos)) 60) (string-to-number (substring time-string (1+ semi-pos) (1- (length time-string)))))) (setq lyric-string (substring lyric-string (length time-string))) (setq emms-lyrics-alist (append emms-lyrics-alist `((,time . ,lyric)))) (setq time 0))))) (setq emms-lyrics-alist (sort emms-lyrics-alist (lambda (a b) (< (car a) (car b)))))) t))) (defun emms-lyrics-create-buffer () "Create `emms-lyrics-buffer' dedicated to lyrics. " ;; leading white space in buffer name to hide the buffer (setq emms-lyrics-buffer (get-buffer-create " *EMMS Lyrics*")) (set-buffer emms-lyrics-buffer) (setq buffer-read-only nil cursor-type nil) (erase-buffer) (mapc (lambda (time-lyric) (insert (cdr time-lyric) "\n")) emms-lyrics-alist) (goto-char (point-min)) (emms-activate-highlighting-mode) (setq buffer-read-only t)) (defun emms-lyrics-start () "Start displaying lryics." (setq emms-lyrics-start-time (current-time) emms-lyrics-pause-time nil emms-lyrics-elapsed-time 0) (when (let ((file (emms-track-get (emms-playlist-current-selected-track) 'name))) (emms-lyrics-read-file (emms-replace-regexp-in-string (concat "\\." (file-name-extension file) "\\'") ".lrc" (file-name-nondirectory file)))) (when emms-lyrics-display-buffer (emms-lyrics-create-buffer)) (emms-lyrics-set-timer))) (defun emms-lyrics-catchup (lrc) "Catchup with later downloaded LRC file(full path). If you write some lyrics crawler, which is running asynchronically, then this function would be useful to call when the crawler finishes its job." (let ((old-start emms-lyrics-start-time)) (setq emms-lyrics-start-time (current-time) emms-lyrics-pause-time nil emms-lyrics-elapsed-time 0) (emms-lyrics-read-file lrc t) (emms-lyrics-set-timer) (emms-lyrics-seek (float-time (time-since old-start))))) (defun emms-lyrics-stop () "Stop displaying lyrics." (interactive) (when emms-lyrics-alist (mapc #'emms-cancel-timer emms-lyrics-timers) (if (or (not emms-player-paused-p) emms-player-stopped-p) (setq emms-lyrics-alist nil emms-lyrics-timers nil emms-lyrics-mode-line-string "")))) (defun emms-lyrics-pause () "Pause displaying lyrics." (if emms-player-paused-p (setq emms-lyrics-pause-time (current-time)) (when emms-lyrics-pause-time (setq emms-lyrics-elapsed-time (+ (float-time (time-subtract emms-lyrics-pause-time emms-lyrics-start-time)) emms-lyrics-elapsed-time))) (setq emms-lyrics-start-time (current-time))) (when emms-lyrics-alist (if emms-player-paused-p (emms-lyrics-stop) (emms-lyrics-set-timer)))) (defun emms-lyrics-seek (sec) "Seek forward or backward SEC seconds lyrics." (setq emms-lyrics-elapsed-time (+ emms-lyrics-elapsed-time (float-time (time-since emms-lyrics-start-time)) sec)) (when (< emms-lyrics-elapsed-time 0) ; back to start point (setq emms-lyrics-elapsed-time 0)) (setq emms-lyrics-start-time (current-time)) (when emms-lyrics-alist (let ((paused-orig emms-player-paused-p)) (setq emms-player-paused-p t) (emms-lyrics-stop) (setq emms-player-paused-p paused-orig)) (emms-lyrics-set-timer))) (defun emms-lyrics-sync (sec) "Synchronize the lyric display at SEC seconds." (setq emms-lyrics-start-time (current-time) emms-lyrics-elapsed-time 0) (emms-lyrics-seek sec)) (defun emms-lyrics-set-timer () "Set timers for displaying lyrics." (setq emms-lyrics-timers '()) (let ((lyrics-alist emms-lyrics-alist) (line 0)) (while lyrics-alist (let ((time (- (caar lyrics-alist) emms-lyrics-elapsed-time)) (lyric (cdar lyrics-alist)) (next-time (and (cdr lyrics-alist) (- (car (cadr lyrics-alist)) emms-lyrics-elapsed-time))) (next-lyric (and (cdr lyrics-alist) (cdr (cadr lyrics-alist))))) (setq line (1+ line)) (when (> time 0) (setq emms-lyrics-timers (append emms-lyrics-timers (list (run-at-time (format "%d sec" time) nil 'emms-lyrics-display-handler lyric next-lyric line (and next-time (- next-time time))))))) (setq lyrics-alist (cdr lyrics-alist)))))) (defun emms-lyrics-mode-line () "Add lyric to the mode line." (or global-mode-string (setq global-mode-string '(""))) (unless (member 'emms-lyrics-mode-line-string global-mode-string) (setq global-mode-string (append global-mode-string '(emms-lyrics-mode-line-string))))) (defun emms-lyrics-restore-mode-line () "Restore the mode line." (setq global-mode-string (remove 'emms-lyrics-mode-line-string global-mode-string)) (force-mode-line-update)) (defun emms-lyrics-display-handler (lyric next-lyric line diff) "DIFF is the timestamp differences between current LYRIC and NEXT-LYRIC; LINE corresponds line number for LYRIC in `emms-lyrics-buffer'." (emms-lyrics-display (format emms-lyrics-display-format lyric) line) (when (and emms-lyrics-display-on-modeline emms-lyrics-scroll-p) (emms-lyrics-scroll lyric next-lyric diff))) (defun emms-lyrics-display (lyric line) "Display LYRIC now. See `emms-lyrics-display-on-modeline' and `emms-lyrics-display-on-minibuffer' on how to config where to display." (when emms-lyrics-alist (when emms-lyrics-display-on-modeline (emms-lyrics-mode-line) (setq emms-lyrics-mode-line-string lyric) ;; (setq emms-lyrics-mode-line-string ; make it fit scroller width ;; (concat emms-lyrics-mode-line-string ;; (make-string ;; (abs (- emms-lyrics-scroll-width (length lyric))) ;; (string-to-char " ")))) (force-mode-line-update)) (when emms-lyrics-display-on-minibuffer (unless (minibuffer-window-active-p (selected-window)) (message lyric))) (when emms-lyrics-display-buffer (with-current-buffer emms-lyrics-buffer (when line (goto-char (point-min)) (forward-line (1- line)) (emms-line-highlight)))))) (defun emms-lyrics-find-lyric (file) "Return full path of found lrc FILE, or nil if not found. Use `emms-source-file-directory-tree-function' to find lrc FILE under current directory and `emms-lyrics-dir'. e.g., (emms-lyrics-find-lyric \"abc.lrc\")" (let* ((track (emms-playlist-current-selected-track)) (lyric-under-curr-dir (concat (file-name-directory (emms-track-get track 'name)) file))) (or (and (eq (emms-track-type track) 'file) (file-exists-p lyric-under-curr-dir) lyric-under-curr-dir) (car (funcall emms-source-file-directory-tree-function emms-lyrics-dir file))))) ;; (setq emms-lyrics-scroll-width 20) (defun emms-lyrics-scroll (lyric next-lyric diff) "Scroll LYRIC to left smoothly in DIFF seconds. DIFF is the timestamp differences between current LYRIC and NEXT-LYRIC." (setq diff (floor diff)) (setq emms-lyrics-scroll-timers '()) (let ((scrolled-lyric (concat lyric " " next-lyric)) (time 0) (pos 0)) (catch 'return (while (< time diff) (setq emms-lyrics-scroll-timers (append emms-lyrics-scroll-timers (list (run-at-time time nil 'emms-lyrics-display (if (>= (length lyric) pos) (substring scrolled-lyric pos) (throw 'return t)) nil)))) (setq time (+ time emms-lyrics-scroll-timer-interval)) (setq pos (1+ pos)))))) ;;; emms-lyrics-mode (defvar emms-lyrics-mode-map (let ((map (make-sparse-keymap))) (define-key map "p" 'emms-lyrics-previous-line) (define-key map "n" 'emms-lyrics-next-line) (define-key map "i" 'emms-lyrics-insert-time) map) "Keymap for `emms-lyrics-mode'.") (defun emms-lyrics-rem* (x y) "The remainder of X divided by Y, with the same sign as X." (let* ((q (floor x y)) (rem (- x (* y q)))) (if (= rem 0) 0 (if (eq (>= x 0) (>= y 0)) rem (- rem y))))) (defun emms-lyrics-insert-time () "Insert lyric time in the form: [01:23.21], then goto the beginning of next line." (interactive) (let* ((total (+ (float-time (time-subtract (current-time) emms-lyrics-start-time)) emms-lyrics-elapsed-time)) (min (/ (* (floor (/ total 60)) 100) 100)) (sec (/ (floor (* (emms-lyrics-rem* total 60) 100)) 100.0))) (insert (emms-replace-regexp-in-string " " "0" (format "[%2d:%2d]" min sec)))) (emms-lyrics-next-line)) (defun emms-lyrics-next-line () "Goto the beginning of next line." (interactive) (forward-line 1)) (defun emms-lyrics-previous-line () "Goto the beginning of previous line." (interactive) (forward-line -1)) (define-derived-mode emms-lyrics-mode nil "Emms Lyric" "Major mode for creating lyric files. \\{emms-lyrics-mode-map}" (run-hooks 'emms-lyrics-mode-hook)) (provide 'emms-lyrics) ;;; emms-lyrics.el ends here �����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������emms-6.00/emms-maint.el�����������������������������������������������������������������������������0000664�0001750�0001750�00000000131�13746063641�013174� 0����������������������������������������������������������������������������������������������������ustar �yrk�����������������������������yrk��������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������;; Copyright (C) 2003-2020 Free Software Foundation, Inc. (add-to-list 'load-path ".") ���������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������emms-6.00/emms-mark.el������������������������������������������������������������������������������0000664�0001750�0001750�00000023515�13746063641�013031� 0����������������������������������������������������������������������������������������������������ustar �yrk�����������������������������yrk��������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������;;; emms-mark.el --- mark track like dired ;; Copyright (C) 2006, 2007, 2008, 2009, 2018 Free Software Foundation, Inc. ;; ;; Author: Ye Wenbin <wenbinye@163.com> ;; This file is part of EMMS. ;; This program is free software; you can redistribute it and/or modify ;; it under the terms of the GNU General Public License as published by ;; the Free Software Foundation; either version 3, or (at your option) ;; any later version. ;; ;; This program is distributed in the hope that it will be useful, ;; but WITHOUT ANY WARRANTY; without even the implied warranty of ;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ;; GNU General Public License for more details. ;; ;; You should have received a copy of the GNU General Public License ;; along with this program; if not, write to the Free Software ;; Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. ;;; Commentary: ;; Provide mark operation to tracks ;; Put this file into your load-path and the following into your ~/.emacs: ;; (require 'emms-mark) ;; To activate it for the current buffer only, do: ;; (emms-mark-mode) ;; To make this the default EMMS mode, do: ;; (setq emms-playlist-default-major-mode 'emms-mark-mode) ;;; Code: (provide 'emms-mark) (require 'cl-lib) (require 'emms) (require 'emms-playlist-mode) ;;{{{ set new description-function (defun emms-mark-track-description (track) "Return a description of the current track." (cl-assert (not (eq (default-value 'emms-track-description-function) 'emms-mark-track-description)) nil (concat "Do not set `emms-track-selection-function' to be" " emms-mark-track-description.")) (concat " " (funcall (default-value 'emms-track-description-function) track))) (defun emms-mark-update-descriptions () "Update the track descriptions in the current buffer." (emms-with-inhibit-read-only-t (save-excursion (goto-char (point-min)) (emms-walk-tracks (emms-playlist-update-track))))) ;;}}} ;;{{{ functions to mark tracks (defvar emms-mark-char ?*) (defvar emms-mark-face-alist '((?* . font-lock-warning-face) (?\040 . emms-playlist-track-face))) (defun emms-mark-track (&optional arg) "Mark the current track. If ARG is positive, also mark the next ARG-1 tracks as well. If ARG is negative, also mark the previous ARG-1 tracks." (interactive "p") (or arg (setq arg 1)) (let ((face (assoc-default emms-mark-char emms-mark-face-alist)) buffer-read-only track) (save-excursion (beginning-of-line) (while (and (not (eobp)) (/= arg 0)) (setq track (get-text-property (point) 'emms-track)) (delete-char 1) (insert (emms-propertize (string emms-mark-char) 'emms-track track)) (backward-char 1) (if (> arg 0) ;; Propertizing forward... (put-text-property (point) (progn (forward-line 1) (point)) 'face face) ;; ... and backward (let ((start (save-excursion (end-of-line) (point)))) (put-text-property (progn (beginning-of-line) (point)) start 'face face)) (forward-line -1)) (setq arg (if (> arg 0) (1- arg) (1+ arg))))))) (defun emms-mark-unmark-track (&optional arg) "Unmark the current track. If ARG is positive, also unmark the next ARG-1 tracks as well. If ARG is negative, also unmark the previous ARG-1 tracks." (interactive "p") (let ((emms-mark-char ?\040)) (emms-mark-track arg))) (defun emms-mark-forward (arg) "Mark one or more tracks and move the point past the newly-marked tracks. See `emms-mark-track' for further details." (interactive "p") (emms-mark-track arg) (forward-line arg)) (defun emms-mark-unmark-forward (arg) "Unmark one or more tracks and move the point past the tracks. See `emms-mark-unmark-track' for further details." (interactive "p") (emms-mark-unmark-track arg) (forward-line arg)) (defun emms-mark-all () "Mark all tracks in the current buffer." (interactive) (save-excursion (goto-char (point-min)) (emms-mark-track (count-lines (point-min) (point-max))))) (defun emms-mark-unmark-all () "Unmark all tracks in the current buffer." (interactive) (emms-mark-do-with-marked-track 'emms-mark-unmark-track)) (defun emms-mark-regexp (regexp arg) "Mark all tracks matching REGEXP. A prefix argument means to unmark them instead." (interactive (list (read-from-minibuffer (if current-prefix-arg "Unmark tracks matching: " "Mark tracks matching: ")) current-prefix-arg)) (let ((emms-mark-char (if arg ?\040 ?*))) (save-excursion (goto-char (point-min)) (while (re-search-forward regexp nil t) (emms-mark-track 1) (forward-line 1))))) (defun emms-mark-toggle () "Toggle all marks in the current buffer." (interactive) (save-excursion (goto-char (point-min)) (let (buffer-read-only) (while (not (eobp)) (if (eq ?\040 (following-char)) (emms-mark-track) (emms-mark-unmark-track)) (forward-line 1))))) (defsubst emms-mark-has-markedp () "Return non-nil if the playlist has a marked line, nil otherwise." (save-excursion (goto-char (point-min)) (re-search-forward (format "^[%c]" emms-mark-char) nil t))) ;;}}} ;;{{{ functions to operate marked tracks (defun emms-mark-do-with-marked-track (func &optional move) "Call FUNC on every marked line in current playlist. The function specified by FUNC takes no argument, so if the track on the marked line is needed, use `emms-playlist-track-at' to get it. The function can also modify the playlist buffer, such as deleting the current line. If the function doesn't move forward, be sure to set the second parameter MOVE to non-nil. Otherwise the function will never exit the loop." (let ((regexp (format "^[%c]" emms-mark-char)) (newfunc func)) (if move (setq newfunc (lambda () (funcall func) (forward-line 1)))) (save-excursion (goto-char (point-min)) (while (re-search-forward regexp nil t) (backward-char 1) ; move to beginning of line (funcall newfunc))))) (defun emms-mark-mapcar-marked-track (func &optional move) "This function does the same thing as `emms-mark-do-with-marked-track', the only difference being that this function collects the result of FUNC." (let ((regexp (format "^[%c]" emms-mark-char)) result (newfunc func)) (if move (setq newfunc (lambda () (let ((res (funcall func))) (forward-line 1) res)))) (save-excursion (goto-char (point-min)) (while (re-search-forward regexp nil t) (backward-char 1) ; move to beginning of line (setq result (cons (funcall newfunc) result))) (nreverse result)))) (defun emms-mark-delete-marked-tracks () "Delete all tracks that have been marked in the current buffer." (interactive) (emms-with-inhibit-read-only-t (emms-mark-do-with-marked-track (lambda nil (delete-region (point) (progn (forward-line 1) (point))))))) (defun emms-mark-kill-marked-tracks () "Kill all tracks that have been marked in the current buffer." (interactive) (let (tracks buffer-read-only) (emms-mark-do-with-marked-track (lambda nil (setq tracks (concat tracks (delete-and-extract-region (point) (progn (forward-line 1) (point))))))) (kill-new tracks))) (defun emms-mark-copy-marked-tracks () "Copy all tracks that have been marked in the current buffer." (interactive) (let (tracks) (emms-mark-do-with-marked-track (lambda nil (setq tracks (concat tracks (buffer-substring (point) (progn (forward-line 1) (point))))))) (kill-new tracks))) ;;}}} ;;{{{ mode stuff (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) (define-key map "D" 'emms-mark-delete-marked-tracks) (define-key map "m" 'emms-mark-forward) (define-key map "u" 'emms-mark-unmark-forward) (define-key map "U" 'emms-mark-unmark-all) (define-key map "t" 'emms-mark-toggle) (define-key map "%m" 'emms-mark-regexp) map) "Keymap for `emms-mark-mode'.") (defun emms-mark-mode () "An EMMS major mode that allows tracks to be marked like dired. \\{emms-mark-mode-map}" (interactive) (if (eq major-mode 'emms-mark-mode) ;; do nothing if we're already in emms-mark-mode nil ;; start emms-playlist-mode exactly once (setq emms-playlist-buffer-p t) (unless (eq major-mode 'emms-playlist-mode) (emms-playlist-mode)) ;; use inherited keymap (set-keymap-parent emms-mark-mode-map (current-local-map)) (use-local-map emms-mark-mode-map) (setq major-mode 'emms-mark-mode mode-name "Emms-Mark") ;; show a blank space at beginning of each line (set (make-local-variable 'emms-track-description-function) 'emms-mark-track-description) (emms-mark-update-descriptions))) (defun emms-mark-mode-disable () "Disable `emms-mark-mode' and return to `emms-playlist-mode'." (interactive) (if (not (eq major-mode 'emms-mark-mode)) ;; do nothing if we're not in emms-mark-mode nil ;; call emms-playlist-mode, saving important variables (let ((selected emms-playlist-selected-marker)) (emms-playlist-mode) (setq emms-playlist-selected-marker selected) (emms-playlist-mode-overlay-selected)) ;; update display (emms-mark-update-descriptions))) ;;}}} ;;; emms-mark.el ends here �����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������emms-6.00/emms-metaplaylist-mode.el�����������������������������������������������������������������0000664�0001750�0001750�00000020100�13746063641�015514� 0����������������������������������������������������������������������������������������������������ustar �yrk�����������������������������yrk��������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������;;; emms-metaplaylist-mode.el --- A major mode for lists of Emms playlists ;; Copyright (C) 2006, 2007, 2008, 2009, 2017-2018 Free Software Foundation, Inc. ;; Author: Yoni Rabkin <yrk@gnu.org> ;; 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: ;; ;; `emms-metaplaylist-mode' creates an interactive list of all the ;; Emms playlist buffers. The currently active buffer is ;; highlighted. You can choose a buffer from the list with RET and get ;; taken there. ;;; Code: (require 'emms) (require 'emms-playlist-mode) ;;; -------------------------------------------------------- ;;; Variables, customisation and faces ;;; -------------------------------------------------------- (defgroup emms-metaplaylist-mode nil "*The Emacs Multimedia System meta-playlist mode." :prefix "emms-metaplaylist-mode-" :group 'multimedia) (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) (defcustom emms-metaplaylist-mode-hooks nil "*List of hooks to run on entry to emms-metaplaylist-mode." :type 'list :group 'emms-metaplaylist-mode) (defface emms-metaplaylist-mode-face '((((class color) (background dark)) (:foreground "AntiqueWhite3")) (((class color) (background light)) (:foreground "red3")) (((type tty) (class mono)) (:inverse-video t)) (t (:background "WhiteSmoke"))) "Face for the buffer names in the playlists buffer." :group 'emms-metaplaylist-mode) (defface emms-metaplaylist-mode-current-face '((((class color) (background dark)) (:foreground "red2")) (((class color) (background light)) (:background "red3" :foreground "white")) (((type tty) (class mono)) (:inverse-video t)) (t (:background "red3"))) "Face for the current buffer name in the playlists buffer." :group 'emms-metaplaylist-mode) ;;; -------------------------------------------------------- ;;; Keymap ;;; -------------------------------------------------------- (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 "RET") 'emms-metaplaylist-mode-goto-current) (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'.") ;;; -------------------------------------------------------- ;;; Metaplaylist ;;; -------------------------------------------------------- (defun emms-metaplaylist-mode-goto-current () "Switch to the buffer at point." (interactive) (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 (buffer-name emms-playlist-buffer) (let ((p nil)) (save-excursion (goto-char (point-min)) (setq p (search-forward-regexp (regexp-quote (buffer-name emms-playlist-buffer)) (point-max) t))) (when (not p) (error "cannot not find the current playlist buffer")) (goto-char p) (goto-char (point-at-bol))))) (defun emms-metaplaylist-mode-create () "Create the meta-playlist buffer." (let ((name emms-metaplaylist-mode-buffer-name) (playlists (emms-metaplaylist-mode-sorted-buffer-list))) (if playlists (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 ;;; -------------------------------------------------------- (defun emms-metaplaylist-mode-new-buffer (buffer-name) "Creates a new buffer playlist buffer BUFFER-NAME." (interactive "sBuffer Name: ") (if (get-buffer buffer-name) (error "Buffer must not exist.") (let ((buf (get-buffer-create buffer-name))) (with-current-buffer buf (emms-playlist-mode) (setq emms-playlist-buffer-p t))) (emms-metaplaylist-mode-update))) (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)))) (emms-metaplaylist-mode-update)) ;;; -------------------------------------------------------- ;;; Mode entry ;;; -------------------------------------------------------- (defun emms-metaplaylist-mode-go () "Single entry point to the metaplaylist interface." (interactive) (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. \\{emms-metaplaylist-mode-map}" ;; (interactive) (kill-all-local-variables) (use-local-map emms-metaplaylist-mode-map) (setq major-mode 'emms-metaplaylist-mode mode-name "Emms-MetaPlaylist") (setq buffer-read-only t) (run-hooks 'emms-metaplaylist-mode-hooks)) (provide 'emms-metaplaylist-mode) ;;; emms-metaplaylist-mode.el ends here ����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������emms-6.00/emms-mode-line-icon.el��������������������������������������������������������������������0000664�0001750�0001750�00000004631�13746063641�014674� 0����������������������������������������������������������������������������������������������������ustar �yrk�����������������������������yrk��������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������;; emms-mode-line-icon.el --- show an icon in the Emacs mode-line ;; Copyright (C) 2006, 2007, 2008, 2009 Free Software Foundation, Inc. ;; Version: 1.1 ;; Keywords: emms ;; Author: Daniel Brockman <daniel@brockman.se> ;; Maintainer: Lucas Bonnet <lucas@rincevent.net> ;; 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 EMMS extension shows an icon in the mode-line next to the ;; info-tag. ;; Code: (require 'emms-mode-line) (defvar emms-mode-line-icon-color "black" "Color of the little icon displayed in the mode-line.") (defvar emms-mode-line-icon-before-format "" "String to put before the icon, in the mode-line. For example, if you want to have something like : \[ <icon> Foo - The Foo Song ] You should set it to \"[\", and set emms-mode-line-format to \"%s ]\"") (defun emms-mode-line-icon-generate (color) `(image :type xpm :ascent center :data ,(concat "/* XPM */ static char *note[] = { /* width height num_colors chars_per_pixel */ \" 10 11 2 1\", /* colors */ \". c " color "\", \"# c None s None\", /* pixels */ \"###...####\", \"###.#...##\", \"###.###...\", \"###.#####.\", \"###.#####.\", \"#...#####.\", \"....#####.\", \"#..######.\", \"#######...\", \"######....\", \"#######..#\"};"))) (defun emms-mode-line-icon-function () (concat " " emms-mode-line-icon-before-format (emms-propertize "NP:" 'display (emms-mode-line-icon-generate emms-mode-line-icon-color)) (emms-mode-line-playlist-current))) (setq emms-mode-line-mode-line-function 'emms-mode-line-icon-function) ;; This is needed for text properties to work in the mode line. (put 'emms-mode-line-string 'risky-local-variable t) (provide 'emms-mode-line-icon) ;;; emms-mode-line-icone.el ends here �������������������������������������������������������������������������������������������������������emms-6.00/emms-mode-line.el�������������������������������������������������������������������������0000664�0001750�0001750�00000012257�13746063641�013751� 0����������������������������������������������������������������������������������������������������ustar �yrk�����������������������������yrk��������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������;;; emms-mode-line.el --- Mode-Line and titlebar infos for emms ;; Copyright (C) 2004, 2005, 2006, 2007, 2008, ;; 2009 Free Software Foundation, Inc. ;; Author: Mario Domgörgen <kanaldrache@gmx.de> ;; Keywords: multimedia ;; 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, 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; see the file COPYING. If not, write to the ;; Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, ;; Boston, MA 02110-1301, USA. ;;; Commentary: ;; ;; To activate put simply the following line in your Emacs: ;; ;; (require 'emms-mode-line) ;; (emms-mode-line 1) ;;; Code: (require 'emms) (defgroup emms-mode-line nil "Showing information on mode-line and titlebar" :prefix "emms-mode-line-" :group 'emms) (defcustom emms-mode-line-mode-line-function 'emms-mode-line-playlist-current "Function for showing infos in mode-line or nil if don't want to." :type '(choice (const :tag "Don't show info on mode-line" nil) function) :group 'emms-mode-line) (defcustom emms-mode-line-titlebar-function nil "Function for showing infos in titlebar or nil if you don't want to." :type '(choice (const :tag "Don't show info on titlebar" nil) function) :group 'emms-mode-line) (defcustom emms-mode-line-format " [ %s ] " "String used for displaying the current track in mode-line and titlebar." :type 'string :group 'emms) (defun emms-mode-line-playlist-current () "Format the currently playing song." (format emms-mode-line-format (emms-track-description (emms-playlist-current-selected-track)))) (defvar emms-mode-line-active-p nil "If non-nil, emms mode line is active.") (defvar emms-mode-line-string "") (defvar emms-mode-line-initial-titlebar frame-title-format) (defun emms-mode-line (arg) "Turn on `emms-mode-line' if ARG is positive, off otherwise." (interactive "p") (or global-mode-string (setq global-mode-string '(""))) (if (and arg (> arg 0)) (progn (setq emms-mode-line-active-p t) (add-hook 'emms-track-updated-functions 'emms-mode-line-alter) (add-hook 'emms-player-finished-hook 'emms-mode-line-blank) (add-hook 'emms-player-stopped-hook 'emms-mode-line-blank) (add-hook 'emms-player-started-hook 'emms-mode-line-alter) (when (and emms-mode-line-mode-line-function (not (member 'emms-mode-line-string global-mode-string))) (setq global-mode-string (append global-mode-string '(emms-mode-line-string)))) (when emms-player-playing-p (emms-mode-line-alter))) (setq emms-mode-line-active-p nil) (remove-hook 'emms-track-updated-functions 'emms-mode-line-alter) (remove-hook 'emms-player-finished-hook 'emms-mode-line-blank) (remove-hook 'emms-player-stopped-hook 'emms-mode-line-blank) (remove-hook 'emms-player-started-hook 'emms-mode-line-alter) (emms-mode-line-restore-titlebar) (emms-mode-line-restore-mode-line))) ;;;###autoload (defun emms-mode-line-enable () "Turn on `emms-mode-line'." (interactive) (emms-mode-line 1) (message "emms mode line enabled")) ;;;###autoload (defun emms-mode-line-disable () "Turn off `emms-mode-line'." (interactive) (emms-mode-line -1) (message "emms mode line disabled")) ;;;###autoload (defun emms-mode-line-toggle () "Toggle `emms-mode-line'." (interactive) (if emms-mode-line-active-p (emms-mode-line-disable) (emms-mode-line-enable))) (defun emms-mode-line-alter (&optional track) "Alter mode-line/titlebar. Optional TRACK is used to be compatible with `emms-track-updated-functions'. It's simply ignored currently." (emms-mode-line-alter-mode-line) (emms-mode-line-alter-titlebar)) (defun emms-mode-line-alter-mode-line () "Update the mode-line with song info." (when (and emms-mode-line-mode-line-function emms-player-playing-p) (setq emms-mode-line-string (funcall emms-mode-line-mode-line-function)) (force-mode-line-update))) (defun emms-mode-line-alter-titlebar () "Update the titlebar with song info." (when emms-mode-line-titlebar-function (setq frame-title-format (list "" emms-mode-line-initial-titlebar (funcall emms-mode-line-titlebar-function))))) (defun emms-mode-line-blank () "Blank mode-line and titlebar but not quit `emms-mode-line'." (setq emms-mode-line-string nil) (force-mode-line-update) (emms-mode-line-restore-titlebar)) (defun emms-mode-line-restore-mode-line () "Restore the mode-line." (when emms-mode-line-mode-line-function (setq global-mode-string (remove 'emms-mode-line-string global-mode-string)) (force-mode-line-update))) (defun emms-mode-line-restore-titlebar () "Restore the mode-line." (when emms-mode-line-titlebar-function (setq frame-title-format (list emms-mode-line-initial-titlebar)))) (provide 'emms-mode-line) ;;; emms-mode-line.el ends here �������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������emms-6.00/emms-player-mpd.el������������������������������������������������������������������������0000664�0001750�0001750�00000142544�13746063641�014155� 0����������������������������������������������������������������������������������������������������ustar �yrk�����������������������������yrk��������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������;;; emms-player-mpd.el --- MusicPD support for EMMS ;; Copyright (C) 2005, 2006, 2007, 2008, 2009, 2014 Free Software Foundation, Inc. ;; Author: Michael Olson <mwolson@gnu.org>, Jose Antonio Ortega Ruiz ;; <jao@gnu.org> ;; 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, 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; see the file COPYING. If not, write to the ;; Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, ;; Boston, MA 02110-1301, USA. ;;; Commentary: ;;; Benefits of MusicPD ;; MusicPD features crossfade, very little skipping, minor CPU usage, ;; many clients, many supported output formats, fast manipulation via ;; network processes, and good abstraction of client and server. ;;; MusicPD setup ;; If you want to set up a local MusicPD server, you'll need to have ;; mpd installed. If you want to use a remote server instance, no ;; installation is needed. ;; The website is at http://musicpd.org/. Debian packages are ;; available. It is recommended to use mpd version 0.12.0 or higher. ;; ;; Copy the example configuration for mpd into ~/.mpdconf and edit it ;; to your needs. Use your top level music directory for ;; music_directory. If your playlists use absolute file names, be ;; certain that music_directory has the leading directory part. ;; ;; Before you try to play anything, but after setting up the above, ;; run `mkdir ~/.mpd && mpd --create-db' to create MusicPD's track ;; database. ;; ;; Check to see if mpd is running. It must be running as a daemon for ;; you to be able to play anything. Launch it by executing "mpd". It ;; can be killed later with "mpd --kill" (or just "killall mpd" if ;; you're not using the latest development version). ;;; EMMS setup ;; Add the following to your config. ;; ;; (require 'emms-player-mpd) ;; Adjust `emms-player-mpd-server-name' and ;; `emms-player-mpd-server-port' to match the location and port of ;; your MusicPD server. ;; ;; (setq emms-player-mpd-server-name "localhost") ;; (setq emms-player-mpd-server-port "6600") ;; If your MusicPD setup requires a password, you will need to do the ;; following. ;; ;; (setq emms-player-mpd-server-password "mypassword") ;; To get track info from MusicPD, do the following. ;; ;; (add-to-list 'emms-info-functions 'emms-info-mpd) ;; To change the volume using MusicPD, do the following. ;; ;; (setq emms-volume-change-function 'emms-volume-mpd-change) ;; Add 'emms-player-mpd to the top of `emms-player-list'. ;; ;; (add-to-list 'emms-player-list 'emms-player-mpd) ;; If you use absolute file names in your m3u playlists (which is most ;; likely), make sure you set `emms-player-mpd-music-directory' to the ;; value of "music_directory" from your MusicPD config. There are ;; additional options available as well, but the defaults should be ;; sufficient for most uses. ;; You can set `emms-player-mpd-sync-playlist' to nil if your master ;; EMMS playlist contains only stored playlists. ;; If at any time you wish to replace the current EMMS playlist buffer ;; with the contents of the MusicPD playlist, type ;; M-x emms-player-mpd-connect. ;; ;; This will also run the relevant seek functions, so that if you use ;; emms-playing-time, the displayed time will be accurate. ;;; Contributors ;; Adam Sjøgren implemented support for changing the volume. (require 'cl-lib) (require 'emms-player-simple) (require 'emms-source-playlist) ; for emms-source-file-parse-playlist (require 'tq) (require 'emms-cache) (require 'emms-url) (eval-when-compile (condition-case nil (progn (require 'url) ; load if available (require 'emms-url)) (error nil))) (defgroup emms-player-mpd nil "EMMS player for MusicPD." :group 'emms-player :prefix "emms-player-mpd-") (defcustom emms-player-mpd (emms-player 'emms-player-mpd-start 'emms-player-mpd-stop 'emms-player-mpd-playable-p) "*Parameters for the MusicPD player." :type '(cons symbol alist) :group 'emms-player-mpd) (defcustom emms-player-mpd-music-directory nil "The value of 'music_directory' in your MusicPD configuration file. Unless your MusicPD is configured to use absolute file names, you must set this variable to the value of 'music_directory' in your MusicPD config." ;; The :format part ensures that entering directories happens on the ;; next line, where there is more space to work with :type '(choice :format "%{%t%}:\n %[Value Menu%] %v" (const nil) directory) :group 'emms-player-mpd) (defun emms-player-mpd-get-supported-regexp () "Returns a regexp of file extensions that MusicPD supports, or nil if we cannot figure it out." (let ((out (shell-command-to-string "mpd --version"))) ;; 0.17.x (if (string-match "Decoders plugins:$" out) (let* ((b (match-end 0)) (e (string-match "Output plugins:$" out)) (plugs (split-string (substring out b e) "\n" t)) (plugs (cl-mapcan (lambda (x) (and (string-match " +\\[.*\\] +\\(.+\\)$" x) (split-string (match-string 1 x) nil t))) plugs)) (b (and (string-match "Protocols:$" out) (match-end 0))) (prots (and b (substring out (+ 2 b) -1))) (prots (split-string (or prots "") nil t))) (concat "\\(\\.\\(m3u\\|pls\\|" (regexp-opt (delq nil plugs)) "\\)\\'\\)\\|\\(\\`" (regexp-opt (delete "file://" prots)) "\\)")) (let ((found-start nil) (supported nil)) (if (string-match "Supported decoders:\\([^0]+?\\)Supported outputs:" out) ;; 0.15.x (setq supported (replace-regexp-in-string "\\[.+?\\]" "" (match-string 1 out))) ;; < 0.15 (setq out (split-string out "\n")) (while (car out) (cond ((string= (car out) "Supported formats:") (setq found-start t)) ((string= (car out) "") (setq found-start nil)) (found-start (setq supported (concat supported (car out))))) (setq out (cdr out)))) ;; Create regexp (when (and (stringp supported) (not (string= supported ""))) (concat "\\`http://\\|\\.\\(m3u\\|pls\\|" (regexp-opt (delq nil (split-string supported))) "\\)\\'")))))) (defcustom emms-player-mpd-supported-regexp ;; Use a sane default, just in case (or (emms-player-mpd-get-supported-regexp) (concat "\\`http://\\|" (emms-player-simple-regexp "m3u" "ogg" "flac" "mp3" "wav" "mod" "au" "aiff"))) "Formats supported by MusicPD." :type 'regexp :set (function (lambda (sym value) (set sym value) (emms-player-set emms-player-mpd 'regex value))) :group 'emms-player-mpd) (defcustom emms-player-mpd-connect-function 'open-network-stream "Function used to initiate the connection to MusicPD. It should take same arguments as `open-network-stream' does." :type 'function :group 'emms-player-mpd) (defcustom emms-player-mpd-server-name (or (getenv "MPD_HOST") "localhost") "The MusicPD server that we should connect to." :type 'string :group 'emms-player-mpd) (defcustom emms-player-mpd-server-port (or (getenv "MPD_PORT") "6600") "The port of the MusicPD server that we should connect to." :type '(choice number string) :group 'emms-player-mpd) (defcustom emms-player-mpd-server-password nil "The password for the MusicPD server that we should connect to." :type '(choice (const :tag "None" nil) string) :group 'emms-player-mpd) (defcustom emms-player-mpd-check-interval 1 "How often to check to see whether MusicPD has advanced to the next song. This may be an integer, a floating point number, or nil. If set to nil, this check will not be periodically performed. This variable is used only if `emms-player-mpd-sync-playlist' is non-nil." :type '(choice (const :tag "Disable check" nil) number) :group 'emms-player-mpd) (defcustom emms-player-mpd-verbose nil "Whether to provide notifications for server connection events and errors." :type 'boolean :group 'emms-player-mpd) (defcustom emms-player-mpd-sync-playlist t "Whether to synchronize the EMMS playlist with the MusicPD playlist. If your EMMS playlist contains music files rather than playlists, leave this set to non-nil. If your EMMS playlist contains stored playlists, set this to nil." :type 'boolean :group 'emms-player-mpd) (emms-player-set emms-player-mpd 'regex emms-player-mpd-supported-regexp) (emms-player-set emms-player-mpd 'pause 'emms-player-mpd-pause) (emms-player-set emms-player-mpd 'resume 'emms-player-mpd-pause) (emms-player-set emms-player-mpd 'seek 'emms-player-mpd-seek) (emms-player-set emms-player-mpd 'seek-to 'emms-player-mpd-seek-to) ;;; Dealing with the MusicPD network process (defvar emms-player-mpd-process nil) (defvar emms-player-mpd-queue nil) (defvar emms-player-mpd-playlist-id nil) (make-variable-buffer-local 'emms-player-mpd-playlist-id) (defvar emms-player-mpd-current-song nil) (defvar emms-player-mpd-last-state nil) (defvar emms-player-mpd-status-timer nil) (defvar emms-player-mpd-status-regexp "^\\(OK\\( MPD \\)?\\|ACK \\[\\([0-9]+\\)@[0-9]+\\] \\(.+\\)\\)\n+\\'" "Regexp that matches the valid status strings that MusicPD can return at the end of a request.") (defun emms-player-mpd-sentinel (proc event) "The process sentinel for MusicPD." (let ((status (process-status proc))) (cond ((string-match "^deleted" event) (when emms-player-mpd-verbose (message "MusicPD process was deleted"))) ((memq status '(exit signal closed)) (emms-player-mpd-close-process t) (when emms-player-mpd-verbose (message "Closed MusicPD process"))) ((memq status '(run open)) (when emms-player-mpd-verbose (message "MusicPD process started successfully"))) (t (when emms-player-mpd-verbose (message "Other MusicPD status change: %s, %s" status event)))))) (defun emms-player-mpd-ensure-process () "Make sure that a MusicPD process is currently active." (unless (and emms-player-mpd-process (processp emms-player-mpd-process) (memq (process-status emms-player-mpd-process) '(run open))) (setq emms-player-mpd-process (if emms-player-mpd-server-port (funcall emms-player-mpd-connect-function "mpd" nil emms-player-mpd-server-name emms-player-mpd-server-port) (make-network-process :name "emms-mpd" :service emms-player-mpd-server-name :family 'local))) (set-process-sentinel emms-player-mpd-process 'emms-player-mpd-sentinel) (setq emms-player-mpd-queue (tq-create emms-player-mpd-process)) (if (fboundp 'set-process-query-on-exit-flag) (set-process-query-on-exit-flag emms-player-mpd-process nil) (set-process-query-on-exit-flag emms-player-mpd-process nil)) ;; send password (when (stringp emms-player-mpd-server-password) (tq-enqueue emms-player-mpd-queue (concat "password " emms-player-mpd-server-password "\n") emms-player-mpd-status-regexp nil #'ignore t)))) (defun emms-player-mpd-close-process (&optional from-sentinel) "Terminate the current MusicPD client process. FROM-SENTINEL indicates whether this was called by the process sentinel, in which case certain checks should not be made." (when (or from-sentinel (and (processp emms-player-mpd-process) (memq (process-status emms-player-mpd-process) '(run open)))) (tq-close emms-player-mpd-queue) (setq emms-player-mpd-queue nil) (setq emms-player-mpd-process nil))) (defun emms-player-mpd-send (question closure fn) "Send the given QUESTION to the MusicPD server. When a reply comes, call FN with CLOSURE and the result." (emms-player-mpd-ensure-process) (unless (string= (substring question -1) "\n") (setq question (concat question "\n"))) (tq-enqueue emms-player-mpd-queue question emms-player-mpd-status-regexp closure fn t)) ;;; Helper functions (defun emms-player-mpd-get-mpd-filename (file) "Turn FILE into something that MusicPD can understand. This usually means removing a prefix." (if (or (not emms-player-mpd-music-directory) (not (eq (aref file 0) ?/)) (string-match "\\`http://" file)) file (file-relative-name file emms-player-mpd-music-directory))) (defun emms-player-mpd-get-emms-filename (file) "Turn FILE into something that EMMS can understand. This usually means adding a prefix." (if (or (not emms-player-mpd-music-directory) (eq (aref file 0) ?/) (string-match "\\`http://" file)) file (expand-file-name file emms-player-mpd-music-directory))) (defun emms-player-mpd-parse-response (response) "Convert the given MusicPD response into a list. The car of the list is special: If an error has occurred, it will contain a cons cell whose car is an error number and whose cdr is the corresponding message. Otherwise, it will be nil." (when (stringp response) (save-match-data (let* ((data (split-string response "\n")) (cruft (last data 3)) (status (if (string= (cadr cruft) "") (car cruft) (cadr cruft)))) (setcdr cruft nil) (when (and (stringp (car data)) (string-match "^OK\\( MPD \\)?" (car data))) (setq data (cdr data))) (if (and (stringp status) (string-match "^ACK \\[\\([0-9]+\\)@[0-9]+\\] \\(.+\\)" status)) (cons (cons (match-string 1 status) (match-string 2 status)) data) (cons nil data)))))) (defun emms-player-mpd-parse-line (line) "Turn the given LINE from MusicPD into a cons cell. The format of the cell is (name . value)." (when (string-match "\\`\\([^:\n]+\\):\\s-*\\(.+\\)" line) (let ((name (match-string 1 line)) (value (match-string 2 line))) (if (and name value) (progn (setq name (downcase name)) (cons name value)) nil)))) (defun emms-player-mpd-get-alist (info) "Turn the given parsed INFO from MusicPD into an alist." (when (and info (null (car info)) ; no error has occurred (cdr info)) ; data exists (let ((alist nil) cell old-cell) (dolist (line (cdr info)) (when (setq cell (emms-player-mpd-parse-line line)) (if (setq old-cell (assoc (car cell) alist)) (setcdr old-cell (cdr cell)) (setq alist (cons cell alist))))) alist))) (defun emms-player-mpd-get-alists (info) "Turn the given parsed INFO from MusicPD into an list of alists. The list will be in reverse order." (when (and info (null (car info)) ; no error has occurred (cdr info)) ; data exists (let ((alists nil) (alist nil) cell) (dolist (line (cdr info)) (when (setq cell (emms-player-mpd-parse-line line)) (if (assoc (car cell) alist) (setq alists (cons alist alists) alist (list cell)) (setq alist (cons cell alist))))) (when alist (setq alists (cons alist alists))) alists))) (defun emms-player-mpd-get-tracks-1 (closure response) (let ((songs (emms-player-mpd-get-alists (emms-player-mpd-parse-response response))) (tracks nil)) (when songs (dolist (song-info songs) (let ((file (cdr (assoc "file" song-info)))) (when file (setq file (emms-player-mpd-get-emms-filename file)) (let* ((type (if (string-match "\\`http://" file) 'url 'file)) (track (emms-track type file))) (emms-info-mpd track song-info) (run-hook-with-args 'emms-track-info-filters track) (setq tracks (cons track tracks))))))) (funcall (car closure) (cdr closure) tracks))) (defun emms-player-mpd-get-tracks (closure callback) "Get the current playlist from MusicPD in the form of a list of EMMS tracks. Call CALLBACK with CLOSURE and result when the request is complete." (emms-player-mpd-send "playlistinfo" (cons callback closure) #'emms-player-mpd-get-tracks-1)) (defun emms-player-mpd-get-status-1 (closure response) (funcall (car closure) (cdr closure) (emms-player-mpd-get-alist (emms-player-mpd-parse-response response)))) (defun emms-player-mpd-get-status (closure callback) "Get status information from MusicPD. It will be returned in the form of an alist by calling CALLBACK with CLOSURE as its first argument, and the status as the second." (emms-player-mpd-send "status" (cons callback closure) #'emms-player-mpd-get-status-1)) (defun emms-player-mpd-get-status-part (closure callback item &optional info) "Get ITEM from the current MusicPD status. Call CALLBACK with CLOSURE and result when the request is complete. If INFO is specified, use that instead of acquiring the necessary info from MusicPD." (if info (funcall callback closure (cdr (assoc item info))) (emms-player-mpd-get-status (cons callback (cons closure item)) (lambda (closure info) (let ((fn (car closure)) (close (cadr closure)) (item (cddr closure))) (funcall fn close (cdr (assoc item info)))))))) (defun emms-player-mpd-get-playlist-id (closure callback &optional info) "Get the current playlist ID from MusicPD. Call CALLBACK with CLOSURE and result when the request is complete. If INFO is specified, use that instead of acquiring the necessary info from MusicPD." (when info (setq callback (lambda (closure id) id))) (emms-player-mpd-get-status-part closure callback "playlist" info)) (defun emms-player-mpd-get-volume (closure callback &optional info) "Get the current volume from MusicPD. Call CALLBACK with CLOSURE and result when the request is complete. If INFO is specified, use that instead of acquiring the necessary info from MusicPD." (when info (setq callback (lambda (closure volume) volume))) (emms-player-mpd-get-status-part closure callback "volume" info)) (defun emms-player-mpd-get-current-song (closure callback &optional info) "Get the current song from MusicPD. This is in the form of a number that indicates the position of the song on the current playlist. Call CALLBACK with CLOSURE and result when the request is complete. If INFO is specified, use that instead of acquiring the necessary info from MusicPD." (when info (setq callback (lambda (closure id) id))) (emms-player-mpd-get-status-part closure callback "song" info)) (defun emms-player-mpd-get-mpd-state (closure callback &optional info) "Get the current state of the MusicPD server. This is either \"play\", \"stop\", or \"pause\". Call CALLBACK with CLOSURE and result when the request is complete. If INFO is specified, use that instead of acquiring the necessary info from MusicPD." (when info (setq callback (lambda (closure id) id))) (emms-player-mpd-get-status-part closure callback "state" info)) (defun emms-player-mpd-get-playing-time (closure callback &optional info) "Get the number of seconds that the current song has been playing, or nil if we cannot obtain this information. Call CALLBACK with CLOSURE and result when the request is complete. If INFO is specified, use that instead of acquiring the necessary info from MusicPD." (if info (emms-player-mpd-get-status-part nil (lambda (closure time) (and time (string-match "\\`\\([0-9]+\\):" time) (string-to-number (match-string 1 time)))) "time" info) (emms-player-mpd-get-status-part (cons callback closure) (lambda (closure time) (funcall (car closure) (cdr closure) (and time (string-match "\\`\\([0-9]+\\):" time) (string-to-number (match-string 1 time))))) "time" info))) (defun emms-player-mpd-select-song (prev-song new-song) "Move to the given song position. The amount to move is the number difference between PREV-SONG and NEW-SONG. NEW-SONG should be a string containing a number. PREV-SONG may be either a string containing a number or nil, which indicates that we should start from the beginning of the buffer and move to NEW-SONG." (with-current-emms-playlist ;; move to current track (goto-char (if (and (stringp prev-song) emms-playlist-selected-marker (marker-position emms-playlist-selected-marker)) emms-playlist-selected-marker (point-min))) ;; seek forward or backward (let ((diff (if (stringp prev-song) (- (string-to-number new-song) (string-to-number prev-song)) (string-to-number new-song)))) (condition-case nil (progn ;; skip to first track if not on one (when (and (> diff 0) (not (emms-playlist-track-at (point)))) (emms-playlist-next)) ;; move to new track (while (> diff 0) (emms-playlist-next) (setq diff (- diff 1))) (while (< diff 0) (emms-playlist-previous) (setq diff (+ diff 1))) ;; select track at point (unless (emms-playlist-selected-track-at-p) (emms-playlist-select (point)))) (error (concat "Could not move to position " new-song)))))) (defun emms-player-mpd-sync-from-emms-1 (closure) (emms-player-mpd-get-playlist-id closure (lambda (closure id) (let ((buffer (car closure)) (fn (cdr closure))) (when (functionp fn) (funcall fn buffer id)))))) (defun emms-player-mpd-sync-from-emms (&optional callback) "Synchronize the MusicPD playlist with the contents of the current EMMS playlist. If CALLBACK is provided, call it with the current EMMS playlist buffer and MusicPD playlist ID when we are done, if there were no errors." (emms-player-mpd-clear) (with-current-emms-playlist (let (tracks) (save-excursion (setq tracks (nreverse (emms-playlist-tracks-in-region (point-min) (point-max))))) (emms-player-mpd-add-several-tracks tracks (cons (current-buffer) callback) #'emms-player-mpd-sync-from-emms-1)))) (defun emms-player-mpd-sync-from-mpd-2 (closure info) (let ((buffer (car closure)) (fn (cadr closure)) (close (cddr closure)) (id (emms-player-mpd-get-playlist-id nil #'ignore info)) (song (emms-player-mpd-get-current-song nil #'ignore info))) (when (buffer-live-p buffer) (let ((emms-playlist-buffer buffer)) (with-current-emms-playlist (setq emms-player-mpd-playlist-id id) (set-buffer-modified-p nil) (if song (emms-player-mpd-select-song nil song) (goto-char (point-min))))) (when (functionp fn) (funcall fn close info))))) (defun emms-player-mpd-sync-from-mpd-1 (closure tracks) (let ((buffer (car closure))) (when (and tracks (buffer-live-p buffer)) (let ((emms-playlist-buffer buffer)) (with-current-emms-playlist (emms-playlist-clear) (mapc #'emms-playlist-insert-track tracks))) (emms-player-mpd-get-status closure #'emms-player-mpd-sync-from-mpd-2)))) (defun emms-player-mpd-sync-from-mpd (&optional closure callback) "Synchronize the EMMS playlist with the contents of the current MusicPD playlist. Namely, clear the EMMS playlist buffer and add tracks to it that are present in the MusicPD playlist. If the current buffer is an EMMS playlist buffer, make it the main EMMS playlist buffer." (when (and emms-playlist-buffer-p (not (eq (current-buffer) emms-playlist-buffer))) (emms-playlist-set-playlist-buffer (current-buffer))) (with-current-emms-playlist (emms-player-mpd-get-tracks (cons emms-playlist-buffer (cons callback closure)) #'emms-player-mpd-sync-from-mpd-1))) (defun emms-player-mpd-detect-song-change-2 (state info) "Perform post-sync tasks after returning from a stop." (setq emms-player-mpd-current-song nil) (setq emms-player-playing-p 'emms-player-mpd) (when (string= state "pause") (setq emms-player-paused-p t)) (emms-player-mpd-detect-song-change info)) (defun emms-player-mpd-detect-song-change-1 (closure info) (let ((song (emms-player-mpd-get-current-song nil #'ignore info)) (state (emms-player-mpd-get-mpd-state nil #'ignore info)) (time (emms-player-mpd-get-playing-time nil #'ignore info)) (err-msg (cdr (assoc "error" info)))) (if (stringp err-msg) (progn (message "MusicPD error: %s" err-msg) (emms-player-mpd-send "clearerror" nil #'ignore)) (cond ((string= state "stop") (if song ;; a track remains: the user probably stopped MusicPD ;; manually, so we'll stop EMMS completely (let ((emms-player-stopped-p t)) (setq emms-player-mpd-last-state "stop") (emms-player-stopped)) ;; no more tracks are left: we probably ran out of things ;; to play, so let EMMS do something further if it wants (unless (string= emms-player-mpd-last-state "stop") (setq emms-player-mpd-last-state "stop") (emms-player-stopped)))) ((and emms-player-mpd-last-state (string= emms-player-mpd-last-state "stop")) ;; resume from a stop that occurred outside of EMMS (setq emms-player-mpd-last-state nil) (emms-player-mpd-sync-from-mpd state #'emms-player-mpd-detect-song-change-2)) ((string= state "pause") nil) ((string= state "play") (setq emms-player-mpd-last-state "play") (unless (or (null song) (and (stringp emms-player-mpd-current-song) (string= song emms-player-mpd-current-song))) (let ((emms-player-stopped-p t)) (emms-player-stopped)) (emms-player-mpd-select-song emms-player-mpd-current-song song) (setq emms-player-mpd-current-song song) (emms-player-started 'emms-player-mpd) (when time (run-hook-with-args 'emms-player-time-set-functions time)))))))) (defun emms-player-mpd-detect-song-change (&optional info) "Detect whether a song change has occurred. This is usually called by a timer. If INFO is specified, use that instead of acquiring the necessary info from MusicPD." (if info (emms-player-mpd-detect-song-change-1 nil info) (emms-player-mpd-get-status nil #'emms-player-mpd-detect-song-change-1))) (defun emms-player-mpd-quote-file (file) "Escape special characters in FILE and surround in double-quotes." (concat "\"" (emms-replace-regexp-in-string "\"" "\\\\\"" (emms-replace-regexp-in-string "\\\\" "\\\\\\\\" file)) "\"")) ;;;###autoload (defun emms-player-mpd-clear () "Clear the MusicPD playlist." (interactive) (when emms-player-mpd-status-timer (emms-cancel-timer emms-player-mpd-status-timer) (setq emms-player-mpd-status-timer nil)) (setq emms-player-mpd-last-state nil) (emms-player-mpd-send "clear" nil #'ignore) (let ((emms-player-stopped-p t)) (emms-player-stopped))) ;;; Adding to the MusicPD playlist (defun emms-player-mpd-add-file (file closure callback) "Add FILE to the current MusicPD playlist. Execute CALLBACK with CLOSURE as its first argument when done. If an error occurs, display a relevant message." (setq file (emms-player-mpd-get-mpd-filename file)) (emms-player-mpd-send (concat "add " (emms-player-mpd-quote-file file)) (cons file (cons callback closure)) (lambda (closure response) (let ((output (emms-player-mpd-parse-response response)) (file (car closure)) (callback (cadr closure)) (close (cddr closure))) (if (car output) (message "MusicPD error: %s: %s" file (cdar output)) (when (functionp callback) (funcall callback close))))))) (defun emms-player-mpd-add-buffer-contents (buffer closure callback) "Load contents of BUFFER into MusicPD by adding each line. Execute CALLBACK with CLOSURE as its first argument when done. This handles both m3u and pls type playlists." (with-current-buffer buffer (goto-char (point-min)) (let ((format (emms-source-playlist-determine-format))) (when format (emms-player-mpd-add-several-files (emms-source-playlist-files format) closure callback))))) (defun emms-player-mpd-add-playlist (playlist closure callback) "Load contents of PLAYLIST into MusicPD by adding each line. Execute CALLBACK with CLOSURE as its first argument when done. This handles both m3u and pls type playlists." ;; This is useful for playlists of playlists (with-temp-buffer (emms-insert-file-contents playlist) (emms-player-mpd-add-buffer-contents (current-buffer) closure callback))) (defun emms-player-mpd-add-streamlist (url closure callback) "Download contents of URL and then add its feeds into MusicPD. Execute CALLBACK with CLOSURE as its first argument when done." ;; This is useful with emms-streams.el (if (fboundp 'url-insert-file-contents) (progn (require 'emms-url) (with-temp-buffer (url-insert-file-contents (emms-url-quote-entire url)) (emms-http-decode-buffer (current-buffer)) (emms-player-mpd-add-buffer-contents (current-buffer) closure callback))) (error (message (concat "You need to install url.el so that" " Emms can retrieve this stream"))))) (defun emms-player-mpd-add (track closure callback) "Add TRACK to the MusicPD playlist. Execute CALLBACK with CLOSURE as its first argument when done." (let ((name (emms-track-get track 'name)) (type (emms-track-get track 'type))) (cond ((eq type 'url) (emms-player-mpd-add-file name closure callback)) ((eq type 'streamlist) (emms-player-mpd-add-streamlist name closure callback)) ((or (eq type 'playlist) (string-match "\\.\\(m3u\\|pls\\)\\'" name)) (emms-player-mpd-add-playlist name closure callback)) ((and (eq type 'file) (string-match emms-player-mpd-supported-regexp name)) (emms-player-mpd-add-file name closure callback))))) (defun emms-player-mpd-add-several-tracks (tracks closure callback) "Add TRACKS to the MusicPD playlist. Execute CALLBACK with CLOSURE as its first argument when done." (when (consp tracks) (while (cdr tracks) (emms-player-mpd-add (car tracks) nil #'ignore) (setq tracks (cdr tracks))) ;; only execute callback on last track (emms-player-mpd-add (car tracks) closure callback))) (defun emms-player-mpd-add-several-files (files closure callback) "Add FILES to the MusicPD playlist. Execute CALLBACK with CLOSURE as its first argument when done." (when (consp files) (while (cdr files) (emms-player-mpd-add-file (car files) nil #'ignore) (setq files (cdr files))) ;; only execute callback on last file (emms-player-mpd-add-file (car files) closure callback))) ;;; EMMS API (defun emms-player-mpd-playable-p (track) "Return non-nil when we can play this track." (and (memq (emms-track-type track) '(file url playlist streamlist)) (string-match (emms-player-get emms-player-mpd 'regex) (emms-track-name track)) (condition-case nil (progn (emms-player-mpd-ensure-process) t) (error nil)))) (defun emms-player-mpd-play (&optional id) "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) (setq id (number-to-string id))) (emms-player-mpd-send (concat "play " id) nil (lambda (closure response) (setq emms-player-mpd-current-song nil) (if emms-player-mpd-check-interval (setq emms-player-mpd-status-timer (run-at-time t emms-player-mpd-check-interval 'emms-player-mpd-detect-song-change)) (emms-player-mpd-detect-song-change))))) ;; we only want to play one track, so don't start the timer (emms-player-mpd-send "play" nil (lambda (closure response) (emms-player-started 'emms-player-mpd))))) (defun emms-player-mpd-start-and-sync-2 (buffer id) (when (buffer-live-p buffer) (let ((emms-playlist-buffer buffer)) (with-current-emms-playlist (setq emms-player-mpd-playlist-id id) (set-buffer-modified-p nil) (let ((track-cnt 0)) (save-excursion (goto-char (if (and emms-playlist-selected-marker (marker-position emms-playlist-selected-marker)) emms-playlist-selected-marker (point-min))) (condition-case nil (while t (emms-playlist-previous) (setq track-cnt (1+ track-cnt))) (error nil))) (emms-player-mpd-play track-cnt)))))) (defun emms-player-mpd-start-and-sync-1 (closure id) (let ((buf-id (with-current-emms-playlist emms-player-mpd-playlist-id))) (if (and (not (buffer-modified-p emms-playlist-buffer)) (stringp buf-id) (string= buf-id id)) (emms-player-mpd-start-and-sync-2 emms-playlist-buffer id) (emms-player-mpd-sync-from-emms #'emms-player-mpd-start-and-sync-2)))) (defun emms-player-mpd-start-and-sync () "Ensure that MusicPD's playlist is up-to-date with EMMS's playlist, and then play the current track. This is called if `emms-player-mpd-sync-playlist' is non-nil." (when emms-player-mpd-status-timer (emms-cancel-timer emms-player-mpd-status-timer) (setq emms-player-mpd-status-timer nil)) (emms-player-mpd-send "clearerror" nil (lambda (closure response) (emms-player-mpd-get-playlist-id nil #'emms-player-mpd-start-and-sync-1)))) (defun emms-player-mpd-connect-1 (closure info) (setq emms-player-mpd-current-song nil) (let* ((state (emms-player-mpd-get-mpd-state nil #'ignore info))) (unless (string= state "stop") (setq emms-player-playing-p 'emms-player-mpd)) (when (string= state "pause") (setq emms-player-paused-p t)) (unless (string= state "stop") (emms-player-mpd-detect-song-change info) (when emms-player-mpd-check-interval (setq emms-player-mpd-status-timer (run-at-time t emms-player-mpd-check-interval 'emms-player-mpd-detect-song-change)))))) ;;;###autoload (defun emms-player-mpd-connect () "Connect to MusicPD and retrieve its current playlist. Afterward, the status of MusicPD will be tracked. This also has the effect of changing the current EMMS playlist to be the same as the current MusicPD playlist. Thus, this function is useful to call if the contents of the EMMS playlist buffer get out-of-sync for some reason." (interactive) (when emms-player-mpd-status-timer (emms-cancel-timer emms-player-mpd-status-timer) (setq emms-player-mpd-status-timer nil)) (emms-player-mpd-sync-from-mpd nil #'emms-player-mpd-connect-1)) (defun emms-player-mpd-start (track) "Starts a process playing TRACK." (interactive) (if (and emms-player-mpd-sync-playlist (not (memq (emms-track-get track 'type) '(streamlist playlist)))) (emms-player-mpd-start-and-sync) (emms-player-mpd-clear) ;; if we have loaded the item successfully, play it (emms-player-mpd-add track nil #'emms-player-mpd-play))) (defun emms-player-mpd-disconnect (&optional no-stop) "Terminate the MusicPD client process and disconnect from MusicPD. If NO-STOP is non-nil, do not indicate to EMMS that we are stopped. This argument is meant to be used when calling this from other functions." (interactive) (emms-cancel-timer emms-player-mpd-status-timer) (setq emms-player-mpd-status-timer nil) (setq emms-player-mpd-current-song nil) (setq emms-player-mpd-last-state nil) (emms-player-mpd-close-process) (unless no-stop (let ((emms-player-stopped-p t)) (emms-player-stopped)))) (defun emms-player-mpd-stop () "Stop the currently playing song." (interactive) (condition-case nil (emms-player-mpd-send "stop" nil #'ignore) (error nil)) (emms-player-mpd-disconnect t) (let ((emms-player-stopped-p t)) (emms-player-stopped))) (defun emms-player-mpd-pause () "Pause the currently playing song." (interactive) (emms-player-mpd-send "pause" nil #'ignore)) (defun emms-player-mpd-seek (amount) "Seek backward or forward by AMOUNT seconds, depending on sign of AMOUNT." (interactive) (emms-player-mpd-get-status amount (lambda (amount info) (let ((song (emms-player-mpd-get-current-song nil #'ignore info)) (secs (emms-player-mpd-get-playing-time nil #'ignore info))) (when (and song secs) (emms-player-mpd-send (concat "seek " song " " (number-to-string (round (+ secs amount)))) nil #'ignore)))))) (defun emms-player-mpd-seek-to (pos) "Seek to POS seconds from the start of the current track." (interactive) (emms-player-mpd-get-current-song pos (lambda (pos song) (when (and song pos) (emms-player-mpd-send (concat "seek " song " " (number-to-string (round pos))) nil #'ignore))))) (defun emms-player-mpd-next () "Move forward by one track in MusicPD's internal playlist." (interactive) (emms-player-mpd-send "next" nil #'ignore)) (defun emms-player-mpd-previous () "Move backward by one track in MusicPD's internal playlist." (interactive) (emms-player-mpd-send "previous" nil #'ignore)) ;;; Volume (defun emms-volume-mpd-change (amount) "Change volume up or down by AMOUNT, depending on whether it is positive or negative." (interactive "MVolume change amount (+ increase, - decrease): ") (emms-player-mpd-get-volume amount (lambda (change volume) (let ((new-volume (+ (string-to-number volume) change))) (emms-player-mpd-send (concat "setvol \"" (number-to-string new-volume) "\"") nil #'ignore))))) ;;; Now playing (defun emms-player-mpd-show-1 (closure response) (let* ((info (emms-player-mpd-get-alist (emms-player-mpd-parse-response response))) (insertp (car closure)) (callback (cadr closure)) (buffer (cddr closure)) (name (cdr (assoc "name" info))) ; radio feeds sometimes set this (file (cdr (assoc "file" info))) (desc nil)) ;; if we are playing lastfm radio, use its show function instead (if (and (boundp 'emms-lastfm-radio-stream-url) (stringp emms-lastfm-radio-stream-url) (string= emms-lastfm-radio-stream-url file)) (with-current-buffer buffer (and (fboundp 'emms-lastfm-np) (emms-lastfm-np insertp callback))) ;; otherwise build and show the description (when info (when name (setq desc name)) (when file (let ((track (emms-dictionary '*track*)) track-desc) (if (string-match "\\`http://" file) (emms-track-set track 'type 'url) (emms-track-set track 'type 'file)) (emms-track-set track 'name file) (emms-info-mpd track info) (run-hook-with-args 'emms-track-info-filters track) (setq track-desc (emms-track-description track)) (when (and (stringp track-desc) (not (string= track-desc ""))) (setq desc (if desc (concat desc ": " track-desc) track-desc)))))) (if (not desc) (unless (functionp callback) (message "Nothing playing right now")) (setq desc (format emms-show-format desc)) (cond ((functionp callback) (funcall callback buffer desc)) (insertp (when (buffer-live-p buffer) (with-current-buffer buffer (insert desc)))) (t (message "%s" desc))))))) ;;;###autoload (defun emms-player-mpd-show (&optional insertp callback) "Describe the current EMMS track in the minibuffer. If INSERTP is non-nil, insert the description into the current buffer instead. If CALLBACK is a function, call it with the current buffer and description as arguments instead of displaying the description or inserting it. This function uses `emms-show-format' to format the current track. It differs from `emms-show' in that it asks MusicPD for the current track, rather than EMMS." (interactive "P") (emms-player-mpd-send "currentsong" (cons insertp (cons callback (current-buffer))) #'emms-player-mpd-show-1)) ;;; Track info (defun emms-info-mpd-process (track info) (dolist (data info) (let ((name (car data)) (value (cdr data))) (setq name (cond ((string= name "artist") 'info-artist) ((string= name "composer") 'info-composer) ((string= name "performer") 'info-performer) ((string= name "title") 'info-title) ((string= name "album") 'info-album) ((string= name "track") 'info-tracknumber) ((string= name "disc") 'info-discnumber) ((string= name "date") 'info-year) ((string= name "genre") 'info-genre) ((string= name "time") (setq value (string-to-number value)) 'info-playing-time) (t nil))) (when name (emms-track-set track name value))))) (defun emms-info-mpd-1 (track response) (let ((info (emms-player-mpd-get-alist (emms-player-mpd-parse-response response)))) (when info (emms-info-mpd-process track info) (emms-track-updated track)))) (defun emms-info-mpd (track &optional info) "Add track information to TRACK. If INFO is specified, use that instead of acquiring the necessary info from MusicPD. This is a useful addition to `emms-info-functions'." (if info (emms-info-mpd-process track info) (when (and (eq 'file (emms-track-type track)) (not (string-match "\\`http://" (emms-track-name track)))) (let ((file (emms-player-mpd-get-mpd-filename (emms-track-name track)))) (when (or emms-player-mpd-music-directory (and file (string-match emms-player-mpd-supported-regexp file))) (condition-case nil (emms-player-mpd-send (concat "find filename " (emms-player-mpd-quote-file file)) track #'emms-info-mpd-1) (error nil))))))) ;;; Caching (defun emms-cache-set-from-mpd-track (track-info) "Dump TRACK-INFO into the EMMS cache. The track should be an alist as per `emms-player-mpd-get-alist'." (when emms-cache-set-function (let ((track (emms-dictionary '*track*)) (name (cdr (assoc "file" track-info)))) (when name (setq name (emms-player-mpd-get-emms-filename name)) (emms-track-set track 'type 'file) (emms-track-set track 'name name) (emms-info-mpd-process track track-info) (funcall emms-cache-set-function 'file name track))))) (defun emms-cache--info-cleanup (info) (let ((xs (mapcar (lambda (x) (and (stringp x) (not (string-match-p "\\`\\(Last-\\|direct\\)" x)) x)) info))) (cons nil (delq nil xs)))) (defun emms-cache-set-from-mpd-directory (dir) "Dump all MusicPD data from DIR into the EMMS cache. This is useful to do when you have recently acquired new music." (interactive (list (if emms-player-mpd-music-directory (emms-read-directory-name "Directory: " emms-player-mpd-music-directory) (read-string "Directory: ")))) (unless (string= dir "") (setq dir (emms-player-mpd-get-mpd-filename dir))) (if emms-cache-set-function (progn (message "Dumping MusicPD data to cache...") (emms-player-mpd-send (concat "listallinfo " dir) nil (lambda (closure response) (message "Dumping MusicPD data to cache...processing") (let ((info (emms-player-mpd-parse-response response))) (when (null (car info)) (let* ((info (emms-cache--info-cleanup info)) (info (emms-player-mpd-get-alists info)) (track 1) (total (length info))) (dolist (track-info info) (message "Dumping MusicPD data to cache...%d/%d" track total) (emms-cache-set-from-mpd-track track-info) (setq track (+ 1 track))) (message "Dumping MusicPD data to cache... %d tracks processed" total))))))) (error "Caching is not enabled"))) (defun emms-cache-set-from-mpd-all () "Dump all MusicPD data into the EMMS cache. This is useful to do once, just before using emms-browser.el, in order to prime the cache." (interactive) (emms-cache-set-from-mpd-directory "")) ;;; Updating tracks (defun emms-player-mpd-update-directory (dir) "Cause the tracks in DIR to be updated in the MusicPD database." (interactive (list (if emms-player-mpd-music-directory (emms-read-directory-name "Directory: " emms-player-mpd-music-directory) (read-string "Directory: ")))) (unless (string= dir "") (setq dir (emms-player-mpd-get-mpd-filename dir))) (emms-player-mpd-send (concat "update " (emms-player-mpd-quote-file dir)) nil (lambda (closure response) (let ((id (cdr (assoc "updating_db" (emms-player-mpd-get-alist (emms-player-mpd-parse-response response)))))) (if id (message "Updating DB with ID %s" id) (message "Could not update the DB")))))) (defun emms-player-mpd-update-all () "Cause all tracks in the MusicPD music directory to be updated in the MusicPD database." (interactive) (emms-player-mpd-update-directory "")) (defvar emms-player-mpd-waiting-for-update-timer nil "Timer object when waiting for MPD update to finish.") (defun emms-player-mpd-update-all-reset-cache () "Update all tracks in the MusicPD music directory. When update finishes, clear the EMMS cache and call `emms-cache-set-from-mpd-all' to dump the MusicPD data into the cache." (interactive) (if emms-player-mpd-waiting-for-update-timer (message "Already waiting for an update to finish.") (emms-player-mpd-send "update" nil 'emms-player-mpd-wait-for-update))) (defun emms-player-mpd-wait-for-update (&optional closure response) "Wait for a currently running mpd update to finish. Afterwards, clear the EMMS cache and call `emms-cache-set-from-mpd-all'." (if response ;; This is the first call after the update command (let ((id (cdr (assoc "updating_db" (emms-player-mpd-get-alist (emms-player-mpd-parse-response response)))))) (if id (progn (message "Updating DB with ID %s. Waiting for the update to finish..." id) (setq emms-player-mpd-waiting-for-update-timer (run-at-time 1 nil 'emms-player-mpd-wait-for-update))) (message "Could not update the DB"))) ;; Otherwise, check if update is still in progress (emms-player-mpd-get-status-part nil (lambda (closure updating) (if updating ;; MPD update still in progress, so wait another second (run-at-time 1 nil 'emms-player-mpd-wait-for-update) ;; MPD update finished (setq emms-player-mpd-waiting-for-update-timer nil) (message "MPD update finished.") (sit-for 1) (clrhash emms-cache-db) (emms-cache-set-from-mpd-all))) "updating_db"))) (provide 'emms-player-mpd) ;;; emms-player-mpd.el ends here ������������������������������������������������������������������������������������������������������������������������������������������������������������emms-6.00/emms-player-mpg321-remote.el��������������������������������������������������������������0000664�0001750�0001750�00000020371�13746063641�015670� 0����������������������������������������������������������������������������������������������������ustar �yrk�����������������������������yrk��������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������;;; emms-player-mpg321-remote.el --- play files with mpg321 -R ;; Copyright (C) 2006, 2007, 2008, 2009 Free Software Foundation, Inc. ;; Author: Damien Elmes <emacs@repose.cx> ;; Keywords: emms, mp3, mpeg, multimedia ;; This file 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, or (at your option) ;; any later version. ;; This file 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 GNU Emacs; see the file COPYING. If not, write to ;; the Free Software Foundation, Inc., 59 Temple Place - Suite 330, ;; Boston, MA 02111-1307, USA. ;;; Commentary: ;; This file provides an emms-player which uses mpg321's remote mode ;; to play files. This is a persistent process which isn't killed each ;; time a new file is played. ;; The remote process copes graciously with errors in music files, and ;; allows you to seek in files. ;; To enable this code, add the following to your emacs configuration: ;; (require 'emms-player-mpg321-remote) ;; (push 'emms-player-mpg321-remote emms-player-list) ;;; Code: (require 'emms) (require 'emms-player-simple) ;; -------------------------------------------------- ;; Variables and configuration ;; -------------------------------------------------- (defgroup emms-player-mpg321-remote nil "*EMMS player using mpg321's remote mode." :group 'emms-player :prefix "emms-player-mpg321-remote") (defcustom emms-player-mpg321-remote-command "mpg321" "*The command name of mpg321." :type 'string :group 'emms-player-mpg321-remote) (defcustom emms-player-mpg321-remote-parameters nil "*Extra arguments to pass to mpg321 when using remote mode For example: (list \"-o\" \"alsa\")" :type '(repeat string) :group 'emms-player-mpg321-remote) (defcustom emms-player-mpg321-remote (emms-player 'emms-player-mpg321-remote-start-playing 'emms-player-mpg321-remote-stop-playing 'emms-player-mpg321-remote-playable-p) "*A player for EMMS." :type '(cons symbol alist) :group 'emms-player-mpg321-remote) (defvar emms-player-mpg321-remote-initial-args (list "--skip-printing-frames=10" "-R" "-") "Initial args to pass to the mpg321 process.") (defvar emms-player-mpg321-remote-process-name "emms-player-mpg321-remote-proc" "The name of the mpg321 remote player process") (defvar emms-player-mpg321-remote-ignore-stop 0 "Number of stop messages to ignore, due to user action.") (defmacro emms-player-mpg321-remote-add (cmd func) `(emms-player-set 'emms-player-mpg321-remote ,cmd ,func)) (emms-player-mpg321-remote-add 'regex (emms-player-simple-regexp "mp3" "mp2")) (emms-player-mpg321-remote-add 'pause 'emms-player-mpg321-remote-pause) (emms-player-mpg321-remote-add 'resume 'emms-player-mpg321-remote-pause) (emms-player-mpg321-remote-add 'seek 'emms-player-mpg321-remote-seek) ;; -------------------------------------------------- ;; Process maintenence ;; -------------------------------------------------- (defun emms-player-mpg321-remote-start-process () "Start a new remote process, and return the process." (let ((process (apply 'start-process emms-player-mpg321-remote-process-name nil emms-player-mpg321-remote-command (append emms-player-mpg321-remote-initial-args emms-player-mpg321-remote-parameters)))) (set-process-sentinel process 'emms-player-mpg321-remote-sentinel) (set-process-filter process 'emms-player-mpg321-remote-filter) process)) (defun emms-player-mpg321-remote-stop () "Stop the currently playing process, if indeed there is one" (let ((process (emms-player-mpg321-remote-process))) (when process (kill-process process) (delete-process process)))) (defun emms-player-mpg321-remote-process () "Return the remote process, if it exists." (get-process emms-player-mpg321-remote-process-name)) (defun emms-player-mpg321-remote-running-p () "True if the remote process exists and is running." (let ((proc (emms-player-mpg321-remote-process))) (and proc (eq (process-status proc) 'run)))) (defun emms-player-mpg321-remote-sentinel (proc str) "Sentinel for determining the end of process" (when (or (eq (process-status proc) 'exit) (eq (process-status proc) 'signal)) ;; reset (setq emms-player-mpg321-remote-ignore-stop 0) (message "Remote process died!"))) (defun emms-player-mpg321-remote-send (text) "Send TEXT to the mpg321 remote process, and add a newline." (let (proc) ;; we shouldn't be trying to send to a dead process (unless (emms-player-mpg321-remote-running-p) (emms-player-mpg321-remote-start-process)) (setq proc (emms-player-mpg321-remote-process)) (process-send-string proc (concat text "\n")))) ;; -------------------------------------------------- ;; Interfacing with emms ;; -------------------------------------------------- (defun emms-player-mpg321-remote-filter (proc str) (let* ((data-lines (split-string str "\n" t)) data line cmd) (dolist (line data-lines) (setq data (split-string line)) (setq cmd (car data)) (cond ;; stop notice ((and (string= cmd "@P") (or (string= (cadr data) "0") (string= (cadr data) "3"))) (emms-player-mpg321-remote-notify-emms)) ;; frame notice ((string= cmd "@F") ;; even though a timer is constantly updating this variable, ;; updating it here will cause it to stay pretty much in sync. (run-hook-with-args 'emms-player-time-set-functions (truncate (string-to-number (nth 3 data))))))))) (defun emms-player-mpg321-remote-start-playing (track) "Start playing a song by telling the remote process to play it. If the remote process is not running, launch it." (unless (emms-player-mpg321-remote-running-p) (emms-player-mpg321-remote-start-process)) (emms-player-mpg321-remote-play-track track)) (defun emms-player-mpg321-remote-notify-emms (&optional user-action) "Tell emms that the current song has finished. If USER-ACTION, set `emms-player-mpg321-remote-ignore-stop' so that we ignore the next message from mpg321." (if user-action (let ((emms-player-ignore-stop t)) ;; so we ignore the next stop message (setq emms-player-mpg321-remote-ignore-stop (1+ emms-player-mpg321-remote-ignore-stop)) (emms-player-stopped)) ;; not a user action (if (not (zerop emms-player-mpg321-remote-ignore-stop)) (setq emms-player-mpg321-remote-ignore-stop (1- emms-player-mpg321-remote-ignore-stop)) (emms-player-stopped)))) (defun emms-player-mpg321-remote-stop-playing () "Stop the current song playing." (emms-player-mpg321-remote-notify-emms t) (emms-player-mpg321-remote-send "stop")) (defun emms-player-mpg321-remote-play-track (track) "Send a play command to the remote, based on TRACK." (emms-player-mpg321-remote-send (concat "load " (emms-track-get track 'name))) (emms-player-started 'emms-player-mpg321-remote)) (defun emms-player-mpg321-remote-playable-p (track) ;; use the simple definition. (emms-player-mpg321-playable-p track)) (defun emms-player-mpg321-remote-pause () "Pause the player." (emms-player-mpg321-remote-send "pause")) (defun emms-player-mpg321-remote-resume () "Resume the player." (emms-player-mpg321-remote-send "pause")) (defun emms-player-mpg321-remote-seek (seconds) "Seek forward or backward in the file." ;; since mpg321 only supports seeking by frames, not seconds, we ;; make a very rough guess as to how much a second constitutes (let ((frame-string (number-to-string (* 35 seconds)))) ;; if we're not going backwards, we need to add a '+' (unless (eq ?- (string-to-char frame-string)) (setq frame-string (concat "+" frame-string))) (emms-player-mpg321-remote-send (concat "jump " frame-string)))) (provide 'emms-player-mpg321-remote) ;;; emms-player-mpg321-remote.el ends here �����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������emms-6.00/emms-player-mplayer.el��������������������������������������������������������������������0000664�0001750�0001750�00000004677�13746063641�015052� 0����������������������������������������������������������������������������������������������������ustar �yrk�����������������������������yrk��������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������;;; emms-player-mplayer.el --- mplayer support for EMMS ;; Copyright (C) 2005, 2006, 2007, 2008, 2009 Free Software Foundation, Inc. ;; Authors: William Xu <william.xwl@gmail.com> ;; Jorgen Schaefer <forcer@forcix.cx> ;; 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 mplayer. It supports pause and ;; seeking. For loading subtitles automatically, try adding ;; "sub-fuzziness=1" to your `~/.mplayer/config', see mplayer manual for ;; more. ;;; Code: (require 'emms-compat) (require 'emms-player-simple) (define-emms-simple-player mplayer '(file url) (concat "\\`\\(http[s]?\\|mms\\)://\\|" (apply #'emms-player-simple-regexp emms-player-base-format-list)) "mplayer" "-slave" "-quiet" "-really-quiet") (define-emms-simple-player mplayer-playlist '(streamlist) "\\`http[s]?://" "mplayer" "-slave" "-quiet" "-really-quiet" "-playlist") (emms-player-set emms-player-mplayer 'pause 'emms-player-mplayer-pause) ;;; Pause is also resume for mplayer (emms-player-set emms-player-mplayer 'resume nil) (emms-player-set emms-player-mplayer 'seek 'emms-player-mplayer-seek) (emms-player-set emms-player-mplayer 'seek-to 'emms-player-mplayer-seek-to) (defun emms-player-mplayer-pause () "Depends on mplayer's -slave mode." (process-send-string emms-player-simple-process-name "pause\n")) (defun emms-player-mplayer-seek (sec) "Depends on mplayer's -slave mode." (process-send-string emms-player-simple-process-name (format "seek %d\n" sec))) (defun emms-player-mplayer-seek-to (sec) "Depends on mplayer's -slave mode." (process-send-string emms-player-simple-process-name (format "seek %d 2\n" sec))) (provide 'emms-player-mplayer) ;;; emms-player-mplayer.el ends here �����������������������������������������������������������������emms-6.00/emms-player-mpv.el������������������������������������������������������������������������0000664�0001750�0001750�00000107475�13746063641�014203� 0����������������������������������������������������������������������������������������������������ustar �yrk�����������������������������yrk��������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������;;; emms-player-mpv.el --- mpv support for EMMS ;; ;; Copyright (C) 2018 Free Software Foundation, Inc. ;; Authors: Mike Kazantsev <mk.fraggod@gmail.com> ;; 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 code provides EMMS backend for using mpv player. ;; ;; It works in one of two modes, depending on `emms-player-mpv-ipc-method' ;; customizable value or installed mpv version: ;; ;; - Using long-running mpv instance and JSON IPC interface to switch tracks ;; and receive player feedback/metadata - for mpv 0.7.0 2014-10-16 and later. ;; ;; - Starting new mpv instance for each track, using its exit ;; as "next track" signal and --input-file interface for pause/seek. ;; Used as a fallback for any older mpv versions (supported in all of them). ;; ;; In default configuration, mpv will read its configuration files ;; (see its manpage for locations), and can display window for ;; video, subtitles, album-art or audio visualization. ;; ;; Useful `emms-player-mpv-parameters' tweaks: ;; ;; - Ignore config file(s): (add-to-list 'emms-player-mpv-parameters "--no-config") ;; - Disable vo window: (add-to-list 'emms-player-mpv-parameters "--vo=null") ;; - Show simple cqt visualizer window: ;; (add-to-list 'emms-player-mpv-parameters ;; "--lavfi-complex=[aid1]asplit[ao][a]; [a]showcqt[vo]") ;; ;; See "M-x customize-group emms-player-mpv" and mpv manpage for more options. ;; ;; See `emms-player-mpv-event-connect-hook' and `emms-player-mpv-event-functions', ;; as well as `emms-player-mpv-ipc-req-send' for handling more mpv events, ;; processing more playback info and metadata from it, as well as extending ;; control over its vast functionality. ;; ;;; Code: (require 'emms) (require 'emms-player-simple) (require 'json) (require 'cl-lib) (defcustom emms-player-mpv (emms-player #'emms-player-mpv-start #'emms-player-mpv-stop #'emms-player-mpv-playable-p) "*Parameters for mpv player." :type '(cons symbol alist) :group 'emms-player-mpv) (emms-player-set emms-player-mpv 'regex (apply #'emms-player-simple-regexp emms-player-base-format-list)) (defcustom emms-player-mpv-command-name "mpv" "mpv binary to use. Can be absolute path or just binary name." :type 'file :group 'emms-player-mpv) (defcustom emms-player-mpv-parameters '("--quiet" "--really-quiet" "--no-audio-display") "Extra command-line arguments for started mpv process(es). Either a list of strings or function returning such list. Extra arguments --idle and --input-file/--input-ipc-server are added automatically, depending on mpv version. Note that unless --no-config option is specified here, mpv will also use options from its configuration files. For mpv binary path, see `emms-player-mpv-command-name'." :type '(choice (repeat :tag "List of mpv arguments" string) function) :group 'emms-player-mpv) (defcustom emms-player-mpv-environment () "List of extra environment variables (\"VAR=value\" strings) to pass on to mpv process. These are added on top of `process-environment' by default. Adding nil as an element to this list will discard emacs `process-environment' and only pass variables that are specified in the list." :type '(repeat (choice string (const :tag "Start from blank environment" nil))) :group 'emms-player-mpv) (defcustom emms-player-mpv-ipc-method nil "Switch for which IPC method to use with mpv. Possible symbols: detect, ipc-server, unix-socket, file. Defaults to nil value, which will cause `emms-player-mpv-ipc-detect' to pick one based on mpv --version output. Using JSON-IPC variants (ipc-server and unix-socket) enables support for various feedback and metadata options from mpv." :type '(choice (const :tag "Auto-detect from mpv --version" nil) (const :tag "Use --input-ipc-server JSON IPC (v0.17.0 2016-04-11)" ipc-server) (const :tag "Use --input-unix-socket JSON IPC (v0.7.0 2014-10-16)" unix-socket) (const :tag "Use --input-file FIFO (any mpv version)" file)) :group 'emms-player-mpv) (defcustom emms-player-mpv-ipc-socket (concat (file-name-as-directory emms-directory) "mpv-ipc.sock") "Unix IPC socket or FIFO to use with mpv --input-* options, depending on `emms-player-mpv-ipc-method' value and/or mpv version." :type 'file :group 'emms-player-mpv) (defvar emms-player-mpv-ipc-proc nil) ; to avoid warnings while keeping useful defs at the top (defcustom emms-player-mpv-update-duration t "Update track duration when played by mpv. Uses `emms-player-mpv-event-functions' hook." :type 'boolean :set (lambda (sym value) (run-at-time 0.1 nil (lambda (value) (if value (add-hook 'emms-player-mpv-event-functions #'emms-player-mpv-info-duration-event-func) (remove-hook 'emms-player-mpv-event-functions #'emms-player-mpv-info-duration-event-func))) value)) :group 'emms-player-mpv) (defcustom emms-player-mpv-update-metadata nil "Update track info (artist, album, name, etc) from mpv events, when it is played. This allows to dynamically update stream info from ICY tags, for example. Uses `emms-player-mpv-event-connect-hook' and `emms-player-mpv-event-functions' hooks." :type 'boolean :set (lambda (sym value) (run-at-time 0.1 nil (lambda (value) (if value (progn (add-hook 'emms-player-mpv-event-connect-hook #'emms-player-mpv-info-meta-connect-func) (add-hook 'emms-player-mpv-event-functions #'emms-player-mpv-info-meta-event-func) (when (process-live-p emms-player-mpv-ipc-proc) (emms-player-mpv-info-meta-connect-func))) (progn (remove-hook 'emms-player-mpv-event-connect-hook #'emms-player-mpv-info-meta-connect-func) (remove-hook 'emms-player-mpv-event-functions #'emms-player-mpv-info-meta-event-func)))) value)) :group 'emms-player-mpv) (defvar emms-player-mpv-proc nil "Running mpv process, controlled over --input-ipc-server/--input-file sockets.") (defvar emms-player-mpv-proc-kill-delay 5 "Delay until SIGKILL gets sent to `emms-player-mpv-proc', if it refuses to exit cleanly on `emms-player-mpv-proc-stop'.") (defvar emms-player-mpv-ipc-proc nil "Unix socket process that communicates with running `emms-player-mpv-proc' instance.") (defvar emms-player-mpv-ipc-buffer " *emms-player-mpv-ipc*" "Buffer to associate with `emms-player-mpv-ipc-proc' socket/pipe process.") (defvar emms-player-mpv-ipc-connect-timer nil "Timer for connection attempts to JSON IPC unix socket.") (defvar emms-player-mpv-ipc-connect-delays '(0.1 0.1 0.1 0.1 0.1 0.1 0.2 0.2 0.3 0.3 0.5 1.0 1.0 2.0) "List of delays before initiating socket connection for new mpv process.") (defvar emms-player-mpv-ipc-connect-command nil "JSON command for `emms-player-mpv-ipc-sentinel' to run as soon as it connects to mpv. I.e. last command that either initiated connection or was used while connecting to mpv. Set by `emms-player-mpv-start' and such, cleared once it gets sent by `emms-player-mpv-ipc-sentinel'.") (defvar emms-player-mpv-ipc-id 1 "Auto-incremented value sent in JSON requests for request_id and observe_property id's. Use `emms-player-mpv-ipc-id-get' to get and increment this value, instead of using it directly. Wraps-around upon reaching `emms-player-mpv-ipc-id-max' (unlikely to ever happen).") (defvar emms-player-mpv-ipc-id-max (expt 2 30) "Max value for `emms-player-mpv-ipc-id' to wrap around after. Should be fine with both mpv and emacs, and probably never reached anyway.") (defvar emms-player-mpv-ipc-req-table nil "Auto-initialized hash table of outstanding API req_ids to their handler funcs.") (defvar emms-player-mpv-ipc-stop-command nil "Internal flag to track when stop command starts/finishes before next loadfile. Set to either nil, t or playback start function to call on end-file event after stop command. This is a workaround for mpv-0.30+ behavior, when 'stop + loadfile' only runs 'stop'.") (defvar emms-player-mpv-event-connect-hook nil "Normal hook run right after establishing new JSON IPC connection to mpv instance and before `emms-player-mpv-ipc-connect-command' if any. Best place to send any observe_property, request_log_messages, enable_event commands. Use `emms-player-mpv-ipc-id-get' to get unique id values for these. See also `emms-player-mpv-event-functions'.") (defvar emms-player-mpv-event-functions nil "List of functions to call for each event emitted from JSON IPC. One argument is passed to each function - JSON line, as sent by mpv and decoded by `json-read-from-string'. See also `emms-player-mpv-event-connect-hook'.") (defvar emms-player-mpv-stopped nil "Non-nil if playback was stopped by call from emms. Similar to `emms-player-stopped-p', but set for future async events, to indicate that playback should stop instead of switching to next track.") (defvar emms-player-mpv-idle-timer (timer-create) "Timer to delay `emms-player-stopped' when mpv unexpectedly goes idle.") (defvar emms-player-mpv-idle-delay 0.5 "Delay before issuing `emms-player-stopped' when mpv unexpectedly goes idle.") (defvar emms-player-mpv-ipc-conn-emacs-26.1-workaround (and (= emacs-major-version 26) (= emacs-minor-version 1)) "Non-nil to enable workaround for issue #31901 in emacs 26.1. Emacs 26.1 fails to indicate missing socket file error for unix socket network processes that were started with :nowait t, so blocking connections are used there instead.") ;; ----- helpers (defvar emms-player-mpv-debug nil "Enable to print sent/received JSON lines and process start/stop events to *Messages* buffer using `emms-player-mpv-debug-msg'.") (defvar emms-player-mpv-debug-ts-offset nil "Timestamp offset for `emms-player-mpv-debug-msg'. Set on first use, with intent to both shorten and obfuscate time in logs.") (defun emms-player-mpv-debug-trim (s) (if (stringp s) (replace-regexp-in-string "\\(^[ \t\n\r]+\\|[ \t\n\r]+$\\)" "" s t t) s)) (defun emms-player-mpv-debug-msg (tpl-or-msg &rest tpl-values) "Print debug message to *Messages* if `emms-player-mpv-debug' is non-nil. Message is only formatted if TPL-VALUES is non-empty. Strips whitespace from start/end of TPL-OR-MSG and strings in TPL-VALUES." (when emms-player-mpv-debug (setq tpl-or-msg (emms-player-mpv-debug-trim tpl-or-msg) tpl-values (seq-map #'emms-player-mpv-debug-trim tpl-values)) (unless tpl-values (setq tpl-or-msg (replace-regexp-in-string "%" "%%" tpl-or-msg t t))) (let ((ts (float-time))) (unless emms-player-mpv-debug-ts-offset (setq emms-player-mpv-debug-ts-offset ts)) (apply 'message (concat "emms-player-mpv %.1f " tpl-or-msg) (- ts emms-player-mpv-debug-ts-offset) tpl-values)))) (defun emms-player-mpv-ipc-fifo-p () "Returns non-nil if --input-file fifo should be used. Runs `emms-player-mpv-ipc-detect' to detect/set `emms-player-mpv-ipc-method' if necessary." (unless emms-player-mpv-ipc-method (setq emms-player-mpv-ipc-method (emms-player-mpv-ipc-detect emms-player-mpv-command-name))) (eq emms-player-mpv-ipc-method 'file)) (defun emms-player-mpv-ipc-detect (cmd) "Run mpv --version and return symbol for best IPC method supported. CMD should be either name of mpv binary to use or full path to it. Return values correspond to `emms-player-mpv-ipc-method' options. Error is signaled if mpv binary fails to run." (with-temp-buffer (let ((exit-code (call-process cmd nil '(t t) nil "--version"))) (unless (zerop exit-code) (insert (format "----- process exited with code %d -----" exit-code)) (error (format "Failed to run mpv binary [%s]:\n%s" cmd (buffer-string)))) (goto-char (point-min)) (pcase (if (re-search-forward "^mpv\\s-+\\(\\([0-9]+\\.?\\)+\\)" nil t 1) (mapconcat (lambda (n) (format "%03d" n)) (seq-map 'string-to-number (split-string (match-string-no-properties 1) "\\." t)) ".") "000.000.000") ((pred (string> "000.006.999")) 'file) ((pred (string> "000.016.999")) 'unix-socket) (- 'ipc-server))))) ;; ----- mpv process (defun emms-player-mpv-proc-playing-p (&optional proc) "Return whether playback in PROC or `emms-player-mpv-proc' is started, which is distinct from 'start-command sent' and 'process is running' states. Used to signal emms via `emms-player-started' and `emms-player-stopped' calls." (let ((proc (or proc emms-player-mpv-proc))) (and proc (process-get proc 'mpv-playing)))) (defun emms-player-mpv-proc-playing (state &optional proc) "Set process mpv-playing state flag for `emms-player-mpv-proc-playing-p'." (let ((proc (or proc emms-player-mpv-proc))) (when proc (process-put proc 'mpv-playing state)))) (defun emms-player-mpv-proc-symbol-id (sym &optional proc) "Get unique process-specific id integer for SYM or nil if it was already requested." (let ((proc (or proc emms-player-mpv-proc)) (sym-id (intern (concat "mpv-sym-" (symbol-name sym))))) (unless (process-get proc sym-id) (let ((id (emms-player-mpv-ipc-id-get))) (process-put proc sym-id id) id)))) (defun emms-player-mpv-proc-init-fifo (path &optional mode) "Create named pipe (fifo) socket for mpv --input-file PATH, if not exists already. Optional MODE should be 12-bit octal integer, e.g. #o600 (safe default). Signals error if mkfifo exits with non-zero code." (let ((attrs (file-attributes path))) (when (and attrs (not (string-prefix-p "p" (nth 8 attrs)))) (delete-file path) (setq attrs nil)) (unless attrs (unless (zerop (call-process "mkfifo" nil nil nil (format "--mode=%o" (or mode #o600)) path)) (error (format "Failed to run mkfifo for mpv --input-file path: %s" path)))))) (defun emms-player-mpv-proc-sentinel (proc ev) (let ((status (process-status proc)) (playing (emms-player-mpv-proc-playing-p proc))) (emms-player-mpv-debug-msg "proc[%s]: %s (status=%s, playing=%s)" proc ev status playing) (when (and (memq status '(exit signal)) playing) (emms-player-stopped)))) (defun emms-player-mpv-proc-init (&rest media-args) "initialize new mpv process as `emms-player-mpv-proc'. MEDIA-ARGS are used instead of --idle, if specified." (emms-player-mpv-proc-stop) (unless (file-directory-p (file-name-directory emms-player-mpv-ipc-socket)) (make-directory (file-name-directory emms-player-mpv-ipc-socket))) (when (emms-player-mpv-ipc-fifo-p) (emms-player-mpv-proc-init-fifo emms-player-mpv-ipc-socket)) (let* ((argv emms-player-mpv-parameters) (argv (append (list emms-player-mpv-command-name) (if (functionp argv) (funcall argv) argv) (list (format "--input-%s=%s" emms-player-mpv-ipc-method emms-player-mpv-ipc-socket)) (or media-args '("--idle")))) (env emms-player-mpv-environment) (process-environment (append (unless (seq-some 'not env) process-environment) (seq-filter 'identity env)))) (setq emms-player-mpv-proc (make-process :name "emms-player-mpv" :buffer nil :command argv :noquery t :sentinel #'emms-player-mpv-proc-sentinel)) (when (emms-player-mpv-ipc-fifo-p) (emms-player-mpv-proc-playing t)) (emms-player-mpv-debug-msg "proc[%s]: start %s" emms-player-mpv-proc argv))) (defun emms-player-mpv-proc-stop () "Stop running `emms-player-mpv-proc' instance via SIGINT, if any. `delete-process' (SIGKILL) timer is started if `emms-player-mpv-proc-kill-delay' is non-nil." (when emms-player-mpv-proc (let ((proc emms-player-mpv-proc)) (emms-player-mpv-debug-msg "proc[%s]: stop" proc) (if (not (process-live-p proc)) (delete-process proc) (emms-player-mpv-proc-playing nil proc) (interrupt-process proc) (when emms-player-mpv-proc-kill-delay (run-at-time emms-player-mpv-proc-kill-delay nil (lambda (proc) (delete-process proc)) proc)))) (setq emms-player-mpv-proc nil))) ;; ----- IPC socket/fifo (defun emms-player-mpv-ipc-sentinel (proc ev) (emms-player-mpv-debug-msg "ipc[%s]: %s" proc ev) (when (memq (process-status proc) '(open run)) (run-hooks 'emms-player-mpv-event-connect-hook) (when emms-player-mpv-ipc-connect-command (let ((cmd emms-player-mpv-ipc-connect-command)) (setq emms-player-mpv-ipc-connect-command nil) (emms-player-mpv-ipc-req-send cmd nil proc))))) (defun emms-player-mpv-ipc-filter (proc s) (when (buffer-live-p (process-buffer proc)) (with-current-buffer (process-buffer proc) (let ((moving (= (point) (process-mark proc)))) (save-excursion (goto-char (process-mark proc)) (insert s) (set-marker (process-mark proc) (point))) (if moving (goto-char (process-mark proc)))) ;; Process/remove all complete lines of json, if any (let ((p0 (point-min))) (while (progn (goto-char p0) (end-of-line) (equal (following-char) ?\n)) (let* ((p1 (point)) (json (buffer-substring p0 p1))) (delete-region p0 (+ p1 1)) (emms-player-mpv-ipc-recv json))))))) (defun emms-player-mpv-ipc-connect (delays) "Make IPC connection attempt, rescheduling if there's no socket by (car DELAYS). (cdr DELAYS) gets passed to next connection attempt, so it can be rescheduled further until function runs out of DELAYS values. Sets `emms-player-mpv-ipc-proc' value to resulting process on success." ;; Note - emacs handles missing unix socket files in different ways between versions: ;; emacs <26 returns nil, emacs 26.1 leaves process in a stuck 'open ;; state (see issue #31901), emacs 26.2+ sets 'file-missing status. ;; None of these cases call sentinel function, so status must also be checked here. (emms-player-mpv-debug-msg "ipc: connect-delay %s" (car delays)) (let ((use-nowait (not emms-player-mpv-ipc-conn-emacs-26.1-workaround))) (setq emms-player-mpv-ipc-proc (condition-case nil (make-network-process :name "emms-player-mpv-ipc" :family 'local :service emms-player-mpv-ipc-socket :nowait use-nowait :coding '(utf-8 . utf-8) :buffer (get-buffer-create emms-player-mpv-ipc-buffer) :noquery t :filter #'emms-player-mpv-ipc-filter :sentinel #'emms-player-mpv-ipc-sentinel) (file-error nil))) (unless (process-live-p emms-player-mpv-ipc-proc) (setq emms-player-mpv-ipc-proc nil)) (when (and emms-player-mpv-ipc-proc (not use-nowait)) (emms-player-mpv-ipc-sentinel emms-player-mpv-ipc-proc 'open))) (when (and (not emms-player-mpv-ipc-proc) delays) (run-at-time (car delays) nil #'emms-player-mpv-ipc-connect (cdr delays)))) (defun emms-player-mpv-ipc-connect-fifo () "Set `emms-player-mpv-ipc-proc' to process wrapper for writing to a named pipe (fifo) file/node or signal error." (setq emms-player-mpv-ipc-proc (start-process-shell-command "emms-player-mpv-input-file" nil (format "cat > \"%s\"" (shell-quote-argument emms-player-mpv-ipc-socket)))) (set-process-query-on-exit-flag emms-player-mpv-ipc-proc nil) (unless emms-player-mpv-ipc-proc (error (format "Failed to start cat-pipe to fifo: %s" emms-player-mpv-ipc-socket))) (when emms-player-mpv-ipc-connect-command (let ((cmd emms-player-mpv-ipc-connect-command)) (setq emms-player-mpv-ipc-connect-command nil) (emms-player-mpv-ipc-fifo-cmd cmd emms-player-mpv-ipc-proc)))) (defun emms-player-mpv-ipc-init () "Initialize new mpv ipc socket/file process and associated state." (emms-player-mpv-ipc-stop) (emms-player-mpv-debug-msg "ipc: init") (if (emms-player-mpv-ipc-fifo-p) (emms-player-mpv-ipc-connect-fifo) (when emms-player-mpv-ipc-connect-timer (cancel-timer emms-player-mpv-ipc-connect-timer)) (with-current-buffer (get-buffer-create emms-player-mpv-ipc-buffer) (erase-buffer)) (setq emms-player-mpv-ipc-id 1 emms-player-mpv-ipc-req-table nil emms-player-mpv-ipc-connect-timer nil emms-player-mpv-ipc-connect-timer (run-at-time (car emms-player-mpv-ipc-connect-delays) nil #'emms-player-mpv-ipc-connect (cdr emms-player-mpv-ipc-connect-delays))))) (defun emms-player-mpv-ipc-stop () (when emms-player-mpv-ipc-proc (emms-player-mpv-debug-msg "ipc: stop") (delete-process emms-player-mpv-ipc-proc) (setq emms-player-mpv-ipc-proc nil))) (defun emms-player-mpv-ipc () "Return open IPC socket/fifo process or nil, (re-)starting mpv/connection if necessary. Return nil when starting async process/connection, and any follow-up command should be stored to `emms-player-mpv-ipc-connect-command' in this case." (unless ;; Don't start idle processes for fifo - just ignore all ipc requests there (and (not (process-live-p emms-player-mpv-proc)) (emms-player-mpv-ipc-fifo-p)) (unless (process-live-p emms-player-mpv-proc) (emms-player-mpv-proc-init)) (unless (process-live-p emms-player-mpv-ipc-proc) (emms-player-mpv-ipc-init)) (and emms-player-mpv-ipc-proc (memq (process-status emms-player-mpv-ipc-proc) '(open run)) emms-player-mpv-ipc-proc))) ;; ----- IPC protocol (defun emms-player-mpv-ipc-id-get () "Get new connection-unique id value, tracked via `emms-player-mpv-ipc-id'." (let ((ipc-id emms-player-mpv-ipc-id)) (setq emms-player-mpv-ipc-id (if (< emms-player-mpv-ipc-id emms-player-mpv-ipc-id-max) (1+ emms-player-mpv-ipc-id) 1)) ipc-id)) (defun emms-player-mpv-ipc-req-send (cmd &optional handler proc) "Send JSON IPC request and assign HANDLER to response for it, if any. CMD value is encoded via `json-encode'. HANDLER func will be called with decoded response JSON as (handler data err), where ERR will be either nil on \"success\", 'connection-error or whatever is in JSON. If HANDLER is nil, default `emms-player-mpv-ipc-req-error-printer' will be used to at least log errors. PROC can be specified to avoid `emms-player-mpv-ipc' call (e.g. from sentinel/filter funcs)." (let ((req-id (emms-player-mpv-ipc-id-get)) (req-proc (or proc (emms-player-mpv-ipc))) (handler (or handler #'emms-player-mpv-ipc-req-error-printer))) (unless emms-player-mpv-ipc-req-table (setq emms-player-mpv-ipc-req-table (make-hash-table))) (let ((json (concat (json-encode (list :command cmd :request_id req-id)) "\n"))) (emms-player-mpv-debug-msg "json >> %s" json) (condition-case err ;; On any disconnect, assume that mpv process is to blame and force restart. (process-send-string req-proc json) (error (emms-player-mpv-proc-stop) (funcall handler nil 'connection-error) (setq handler nil)))) (when handler (puthash req-id handler emms-player-mpv-ipc-req-table)))) (defun emms-player-mpv-ipc-req-resolve (req-id data err) "Run handler-func for specified req-id." (when emms-player-mpv-ipc-req-table (let ((handler (gethash req-id emms-player-mpv-ipc-req-table)) (err (if (string= err "success") nil err))) (remhash req-id emms-player-mpv-ipc-req-table) (when handler (funcall handler data err))))) (defun emms-player-mpv-ipc-req-error-printer (data err) "Simple default `emms-player-mpv-ipc-req-send' handler to log errors, if any." (when err (message "emms-player-mpv ipc-error: %s" err))) (defun emms-player-mpv-ipc-recv (json) "Handler for all JSON lines from mpv process. Only used with JSON IPC, never called with --input-file as there's no feedback there." (emms-player-mpv-debug-msg "json << %s" json) (let* ((json-data (json-read-from-string json)) (req-id (alist-get 'request_id json-data)) (ev (alist-get 'event json-data))) (when req-id ;; Response to command (emms-player-mpv-ipc-req-resolve req-id (alist-get 'data json-data) (alist-get 'error json-data))) (when ev ;; mpv event (emms-player-mpv-event-handler json-data) (run-hook-with-args 'emms-player-mpv-event-functions json-data)))) (defun emms-player-mpv-ipc-fifo-cmd (cmd &optional proc) "Send --input-file command string for older mpv versions. PROC can be specified to avoid `emms-player-mpv-ipc' call." (let ((proc (or proc (emms-player-mpv-ipc))) (cmd-line (concat (mapconcat (lambda (s) (format "%s" s)) cmd " ") "\n"))) (emms-player-mpv-debug-msg "fifo >> %s" cmd-line) (process-send-string proc cmd-line))) (defun emms-player-mpv-observe-property (sym) "Send mpv observe_property command for property identified by SYM. Only sends command once per process, removing any potential duplication if used for same properties from different functions." (let ((id (emms-player-mpv-proc-symbol-id sym))) (when id (emms-player-mpv-ipc-req-send `(observe_property ,id ,sym))))) (defun emms-player-mpv-event-idle () "Delayed check for switching tracks when mpv goes idle for no good reason." (emms-player-mpv-debug-msg "idle-check (stopped=%s)" emms-player-mpv-stopped) (unless emms-player-mpv-stopped (emms-player-stopped))) (defun emms-player-mpv-event-handler (json-data) "Handler for supported mpv events, including property changes. Called before `emms-player-mpv-event-functions' and does same thing as these hooks." (pcase (alist-get 'event json-data) ("playback-restart" ;; Separate emms-player-mpv-proc-playing state is used for emms started/stopped signals, ;; because start-file/end-file are also emitted after track-change and for playlists, ;; and don't correspond to actual playback state. (unless (emms-player-mpv-proc-playing-p) (emms-player-mpv-proc-playing t) (emms-player-started emms-player-mpv))) ("end-file" (when (emms-player-mpv-proc-playing-p) (emms-player-mpv-proc-playing nil) (emms-player-stopped)) (when emms-player-mpv-ipc-stop-command (unless (eq emms-player-mpv-ipc-stop-command t) (funcall emms-player-mpv-ipc-stop-command)) (setq emms-player-mpv-ipc-stop-command nil))) ("idle" ;; Can mean any kind of error before or during playback. ;; Example can be access/format error, resulting in start+end without playback-restart. (cancel-timer emms-player-mpv-idle-timer) (setq emms-player-mpv-idle-timer (run-at-time emms-player-mpv-idle-delay nil #'emms-player-mpv-event-idle) emms-player-mpv-ipc-stop-command nil)) ("start-file" (cancel-timer emms-player-mpv-idle-timer)))) ;; ----- Metadata update hooks (defun emms-player-mpv-info-meta-connect-func () "Hook function for `emms-player-mpv-event-connect-hook' to update metadata from mpv." (emms-player-mpv-observe-property 'metadata)) (defun emms-player-mpv-info-meta-event-func (json-data) "Hook function for `emms-player-mpv-event-functions' to update metadata from mpv." (when (and (string= (alist-get 'event json-data) "property-change") (string= (alist-get 'name json-data) "metadata")) (let ((info-alist (alist-get 'data json-data))) (when info-alist (emms-player-mpv-info-meta-update-track info-alist))))) (defun emms-player-mpv-info-meta-update-track (info-alist &optional track) "Update TRACK with mpv metadata from INFO-ALIST. `emms-playlist-current-selected-track' is used by default." (mapc (lambda (cc) (setcar cc (intern (downcase (symbol-name (car cc)))))) info-alist) (cl-macrolet ((key (k) `(alist-get ',k info-alist)) (set-track-info (track &rest body) (cons 'progn (cl-loop for (k v) on body by 'cddr collect `(let ((value ,v)) (when value (emms-track-set ,track ',(intern (format "info-%s" k)) value))))))) (unless track (setq track (emms-playlist-current-selected-track))) (set-track-info track title (or (key title) (key icy-title)) artist (or (key artist) (key album_artist) (key icy-name)) album (key album) tracknumber (key track) year (key date) genre (key genre) note (key comment)) (emms-track-updated track))) (defun emms-player-mpv-info-duration-event-func (json-data) "Hook function for `emms-player-mpv-event-functions' to update track duration from mpv." (when (string= (alist-get 'event json-data) "playback-restart") (emms-player-mpv-info-duration-check))) (defun emms-player-mpv-info-duration-check () "Check whether current mpv track has reliable duration info and request it." (emms-player-mpv-ipc-req-send '(get_property stream-end) (lambda (pts-end err) (if err (unless (and (stringp err) (string= err "property unavailable")) (emms-player-mpv-ipc-req-error-printer pts-end err)) (when pts-end (emms-player-mpv-ipc-req-send '(get_property duration) #'emms-player-mpv-info-duration-handler)))))) (defun emms-player-mpv-info-duration-handler (duration err) "Duration property request handler to update it for current emms track." (if err (emms-player-mpv-debug-msg "duration-req-error: %s" err) ;; Duration can be nil or 0 for network streams, depending on version/stream (when (and (numberp duration) (> duration 0)) (let ((duration (round duration)) (track (emms-playlist-current-selected-track))) (emms-track-set track 'info-playing-time duration) (emms-track-set track 'info-playing-time-min (/ duration 60)) (emms-track-set track 'info-playing-time-sec (% duration 60)))))) ;; ----- High-level EMMS interface (defun emms-player-mpv-cmd (cmd &optional handler) "Send mpv command to process/connection if both are running, or otherwise schedule start/connect and set `emms-player-mpv-ipc-start-track' for `emms-player-mpv-ipc-sentinel'." (setq emms-player-mpv-ipc-connect-command nil) (let ((proc (emms-player-mpv-ipc))) (if proc (if (emms-player-mpv-ipc-fifo-p) (emms-player-mpv-ipc-fifo-cmd cmd proc) (emms-player-mpv-ipc-req-send cmd handler proc)) (setq emms-player-mpv-ipc-connect-command cmd)))) (defmacro emms-player-mpv-cmd-prog (cmd &rest handler-body) "Macro around `emms-player-mpv-cmd' that creates handler callback (see `emms-player-mpv-ipc-req-send') from HANDLER-BODY forms, which have following bindings: - mpv-cmd for CMD. - mpv-data for response data (decoded json, nil if none). - mpv-error for response error (nil if no error, decoded json or 'connection-error)." `(emms-player-mpv-cmd ,cmd (apply-partially (lambda (mpv-cmd mpv-data mpv-error) ,@handler-body) ,cmd))) (defun emms-player-mpv-playable-p (track) (memq (emms-track-type track) '(file url streamlist playlist))) (defun emms-player-mpv-start-error-handler (mpv-cmd mpv-data mpv-error) "Playback-restart error handler for `emms-player-mpv-cmd', to restart/reconnect-to mpv and re-run MPV-CMD, if there was any issue when trying to start it initially." (if (eq mpv-error 'connection-error) ;; Reconnect and restart playback if current connection fails (e.g. mpv crash) (emms-player-mpv-cmd-prog (emms-player-mpv-cmd mpv-cmd) (emms-player-mpv-cmd `(set pause no))) (emms-player-mpv-cmd `(set pause no)))) (defun emms-player-mpv-start (track) (setq emms-player-mpv-stopped nil) (emms-player-mpv-proc-playing nil) (let ((track-name (emms-track-get track 'name)) (track-is-playlist (memq (emms-track-get track 'type) '(streamlist playlist)))) (if (emms-player-mpv-ipc-fifo-p) (progn ;; ipc-stop is to clear any buffered commands (emms-player-mpv-ipc-stop) (emms-player-mpv-proc-init (if track-is-playlist "--playlist" "--") track-name) (emms-player-started emms-player-mpv)) (let* ((start-cmd (list (if track-is-playlist 'loadlist 'loadfile) track-name 'replace)) (start-func `(lambda () (emms-player-mpv-cmd ',start-cmd (apply-partially 'emms-player-mpv-start-error-handler ',start-cmd))))) (if emms-player-mpv-ipc-stop-command (setq emms-player-mpv-ipc-stop-command start-func) (funcall start-func)))))) (defun emms-player-mpv-stop () (setq emms-player-mpv-stopped t emms-player-mpv-ipc-stop-command t) (emms-player-mpv-proc-playing nil) (emms-player-mpv-cmd `(stop)) (emms-player-stopped)) (defun emms-player-mpv-pause () (emms-player-mpv-cmd `(set pause yes))) (defun emms-player-mpv-resume () (emms-player-mpv-cmd `(set pause no))) (defun emms-player-mpv-seek (sec) (emms-player-mpv-cmd `(seek ,sec relative))) (defun emms-player-mpv-seek-to (sec) (emms-player-mpv-cmd `(seek ,sec absolute))) (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) (provide 'emms-player-mpv) ;;; emms-player-mpv.el ends here ���������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������emms-6.00/emms-player-simple.el���������������������������������������������������������������������0000664�0001750�0001750�00000020014�13746063641�014651� 0����������������������������������������������������������������������������������������������������ustar �yrk�����������������������������yrk��������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������;;; emms-player-simple.el --- A generic simple player. ;; Copyright (C) 2003, 2004, 2006, 2007, 2008, ;; 2009 Free Software Foundation, Inc. ;; Authors: Ulrik Jensen <terryp@daimi.au.dk> ;; Jorgen Schäfer <forcer@forcix.cx> ;; Keywords: emms, mpg321, ogg123 ;; 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, 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; see the file COPYING. If not, write to the ;; Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, ;; Boston, MA 02110-1301, USA. ;;; Commentary: ;; This is a simple player interface - if you have an external player ;; that just expects the filename to play as an argument, this should ;; be able to use it. See the define-emms-simple-player lines at the ;; end of this file for examples. ;; Add the following to your `emms-player-list': ;; emms-player-mpg321 ;; emms-player-ogg123 ;;; Code: ;; Version control (defvar emms-player-simple-version "0.2 $Revision: 1.26 $" "Simple player for EMMS version string.") ;; $Id: emms-player-simple.el,v 1.26 2005/08/02 15:27:51 forcer Exp $ (require 'emms) ;; Customization (defmacro define-emms-simple-player (name types regex command &rest args) "Define a simple player with the use of `emms-define-player'. NAME is used to contruct the name of the function like emms-player-NAME. TYPES is a list of track types understood by this player. REGEX must be a regexp that matches the filenames the player can play. COMMAND specifies the command line arguement to call the player and ARGS are the command line arguements." (let ((group (intern (concat "emms-player-" (symbol-name name)))) (command-name (intern (concat "emms-player-" (symbol-name name) "-command-name"))) (parameters (intern (concat "emms-player-" (symbol-name name) "-parameters"))) (player-name (intern (concat "emms-player-" (symbol-name name)))) (start (intern (concat "emms-player-" (symbol-name name) "-start"))) (stop (intern (concat "emms-player-" (symbol-name name) "-stop"))) (playablep (intern (concat "emms-player-" (symbol-name name) "-playable-p")))) `(progn (defgroup ,group nil ,(concat "EMMS player for " command ".") :group 'emms-player :prefix ,(concat "emms-player-" (symbol-name name) "-")) (defcustom ,command-name ,command ,(concat "*The command name of " command ".") :type 'string :group ',group) (defcustom ,parameters ',args ,(concat "*The arguments to `" (symbol-name command-name) "'.") :type '(repeat string) :group ',group) (defcustom ,player-name (emms-player ',start ',stop ',playablep) ,(concat "*A player for EMMS.") :type '(cons symbol alist) :group ',group) (emms-player-set ,player-name 'regex ,regex) (emms-player-set ,player-name 'pause 'emms-player-simple-pause) (emms-player-set ,player-name 'resume 'emms-player-simple-resume) (defun ,start (track) "Start the player process." (emms-player-simple-start (emms-track-name track) ,player-name ,command-name ,parameters)) (defun ,stop () "Stop the player process." (emms-player-simple-stop)) (defun ,playablep (track) "Return non-nil when we can play this track." (and (executable-find ,command-name) (memq (emms-track-type track) ,types) (string-match (emms-player-get ,player-name 'regex) (emms-track-name track))))))) ;; Global variables (defvar emms-player-simple-process-name "emms-player-simple-process" "The name of the simple player process") (defun emms-player-simple-stop () "Stop the currently playing process, if indeed there is one" (let ((process (get-process emms-player-simple-process-name))) (when process (kill-process process) (delete-process process)))) ;; Utility-functions (defun emms-player-simple-start (filename player cmdname params) "Starts a process playing FILENAME using the specified CMDNAME with the specified PARAMS. PLAYER is the name of the current player." (let ((process (apply 'start-process emms-player-simple-process-name nil cmdname ;; splice in params here (append params (list filename))))) ;; add a sentinel for signaling termination (set-process-sentinel process 'emms-player-simple-sentinel)) (emms-player-started player)) (defun emms-player-simple-sentinel (proc str) "Sentinel for determining the end of process" (when (or (eq (process-status proc) 'exit) (eq (process-status proc) 'signal)) (emms-player-stopped))) (defun emms-player-simple-pause () "Pause the player by sending a SIGSTOP." (signal-process (get-process emms-player-simple-process-name) 'SIGSTOP)) (defun emms-player-simple-resume () "Resume the player by sending a SIGCONT." (signal-process (get-process emms-player-simple-process-name) 'SIGCONT)) (defun emms-player-simple-regexp (&rest extensions) "Return a regexp matching all EXTENSIONS, case-insensitively." (concat "\\.\\(" (mapconcat (lambda (extension) (mapconcat (lambda (char) (let ((u (upcase char)) (d (downcase char))) (if (= u d) (format "%c" char) (format "[%c%c]" u d)))) extension "")) extensions "\\|") "\\)\\'")) (define-emms-simple-player mpg321 '(file url) (emms-player-simple-regexp "mp3" "mp2") "mpg321") (define-emms-simple-player ogg123 '(file) (emms-player-simple-regexp "ogg" "flac") "ogg123") (define-emms-simple-player speexdec '(file) (emms-player-simple-regexp "spx") "speexdec") (define-emms-simple-player playsound '(file) (emms-player-simple-regexp "wav") "playsound") (define-emms-simple-player mikmod '(file) (emms-player-simple-regexp "669" "amf" "dsm" "far" "gdm" "it" "imf" "mod" "med" "mtm" "okt" "s3m" "stm" "stx" "ult" "apun" "xm" "mod") "mikmod" "-q" "-p" "1" "-X") (define-emms-simple-player timidity '(file) (emms-player-simple-regexp "mid" "rmi" "rcp" "r36" "g18" "g36" "mfi") "timidity") (define-emms-simple-player fluidsynth '(file) (emms-player-simple-regexp "mid") "fluidsynth" "-aalsa" "-in" "/media/music/sf/FluidR3-GM.SF2") (define-emms-simple-player alsaplayer '(file url) (concat "\\`http[s]?://\\|" (emms-player-simple-regexp "ogg" "mp3" "wav" "flac" "pls" "m3u")) "alsaplayer" "--quiet" "--nosave" "\"--interface text\"") (emms-player-set emms-player-alsaplayer 'pause 'emms-player-alsaplayer-pause) ;;; Pause is also resume for alsaplayer (emms-player-set emms-player-alsaplayer 'resume nil) (emms-player-set emms-player-alsaplayer 'seek 'emms-player-alsaplayer-seek) (defun emms-player-alsaplayer-pause () (call-process "alsaplayer" nil nil nil "--pause")) (defun emms-player-alsaplayer-seek (sec) (call-process "alsaplayer" nil nil nil "--relative" (format "%d" sec))) (provide 'emms-player-simple) ;;; emms-player-simple.el ends here ��������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������emms-6.00/emms-player-vlc.el������������������������������������������������������������������������0000664�0001750�0001750�00000006077�13746063641�014161� 0����������������������������������������������������������������������������������������������������ustar �yrk�����������������������������yrk��������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������;;; emms-player-vlc.el --- vlc support for EMMS ;; Copyright (C) 2008, 2009 Free Software Foundation, Inc. ;; Authors: Yoni Rabkin <yrk@gnu.org> ;; 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-compat) (require 'emms-player-simple) ;; I use this macro, and later override some of the stuff it defines ;; in order to accomodate VLC's particular idioms. (define-emms-simple-player vlc '(file url) (concat "\\`\\(http[s]?\\|mms\\)://\\|" (apply #'emms-player-simple-regexp emms-player-base-format-list)) "vlc" "--intf=rc") (define-emms-simple-player vlc-playlist '(streamlist) "\\`http[s]?://" "vlc" "--intf=rc") ;; (kludge) By default, VLC does not quit after finishing to play a ;; track, so the player sentinel has no way of telling that the next ;; track should be played. Therefore I redefine this low-level ;; function and add a "quit" track which is invisible to Emms. (defadvice emms-player-vlc-start (around quit-vlc-after-finish activate) (let ((process (apply 'start-process emms-player-simple-process-name nil emms-player-vlc-command-name ;; splice in params here (append emms-player-vlc-parameters (list (emms-track-name (ad-get-arg 0))) '("vlc://quit"))))) ;; add a sentinel for signaling termination (set-process-sentinel process 'emms-player-simple-sentinel)) (emms-player-started emms-player-vlc)) (defun emms-player-vlc-pause () "Depends on vlc's rc mode." (process-send-string emms-player-simple-process-name "pause\n")) (defun emms-player-vlc-seek (sec) "Seek relative within a stream." (when (not (= 0 sec)) (process-send-string emms-player-simple-process-name (if (< 0 sec) "fastforward\n" "rewind\n")))) (defun emms-player-vlc-seek-to (sec) "Seek to time SEC within the stream." (process-send-string emms-player-simple-process-name (format "seek %d\n" sec))) (emms-player-set emms-player-vlc 'pause 'emms-player-vlc-pause) (emms-player-set emms-player-vlc 'resume nil) ; pause is also resume (emms-player-set emms-player-vlc 'start 'emms-player-vlc-start) (emms-player-set emms-player-vlc 'seek 'emms-player-vlc-seek) (emms-player-set emms-player-vlc 'seek-to 'emms-player-vlc-seek-to) (provide 'emms-player-vlc) ;;; emms-player-vlc.el ends here �����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������emms-6.00/emms-player-xine.el�����������������������������������������������������������������������0000664�0001750�0001750�00000006005�13746063641�014327� 0����������������������������������������������������������������������������������������������������ustar �yrk�����������������������������yrk��������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������;;; emms-player-xine.el --- xine support for EMMS ;; Copyright (C) 2007, 2008, 2009 Free Software Foundation, Inc. ;; Author: Tassilo Horn <tassilo@member.fsf.org> ;; 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 xine. It supports pause and ;; seeking. ;;; Code: ;; TODO: The video window cannot be disabled. I asked on ;; gmane.comp.video.xine.user (<87y7ohqcbq.fsf@baldur.tsdh.de>)... ;; TODO: Implement seek-to with "SetPositionX%\n" where X is in {0,10,..,90} (require 'emms-player-simple) (define-emms-simple-player xine '(file url) (concat "\\`\\(http[s]?\\|mms\\)://\\|" (emms-player-simple-regexp "ogg" "mp3" "wav" "mpg" "mpeg" "wmv" "wma" "mov" "avi" "divx" "ogm" "ogv" "asf" "mkv" "rm" "rmvb" "mp4" "flac" "vob")) "xine" "--no-gui" "--no-logo" "--no-splash" "--no-reload" "--stdctl") (emms-player-set emms-player-xine 'pause 'emms-player-xine-pause) ;;; Pause is also resume for xine (emms-player-set emms-player-xine 'resume nil) (emms-player-set emms-player-xine 'seek 'emms-player-xine-seek) (defun emms-player-xine-pause () "Depends on xine's --stdctl mode." (process-send-string emms-player-simple-process-name "pause\n")) (defun emms-player-xine-seek (secs) "Depends on xine's --stdctl mode." ;; xine-ui's stdctl supports only seeking forward/backward in 7/15/30 and 60 ;; second steps, so we take the value that is nearest to SECS. (let ((s (emms-nearest-value secs '(-60 -30 -15 -7 7 15 30 60)))) (when (/= s secs) (message (concat "EMMS: Xine only supports seeking for [+/-] 7/15/30/60 " "seconds, so we seeked %d seconds") s)) (process-send-string emms-player-simple-process-name (if (< s 0) (format "SeekRelative%d\n" s) (format "SeekRelative+%d\n" s))))) (defun emms-nearest-value (val list) "Returns the value of LIST which is nearest to VAL. LIST should be a list of integers." (let* ((nearest (car list)) (dist (abs (- val nearest)))) (dolist (lval (cdr list)) (let ((ndist (abs (- val lval)))) (when (< ndist dist) (setq nearest lval dist ndist)))) nearest)) (provide 'emms-player-xine) ;;; emms-player-xine.el ends here ���������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������emms-6.00/emms-playing-time.el����������������������������������������������������������������������0000664�0001750�0001750�00000020755�13746063641�014501� 0����������������������������������������������������������������������������������������������������ustar �yrk�����������������������������yrk��������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������;;; emms-playing-time.el --- Display emms playing time on mode line ;; Copyright (C) 2005, 2006, 2007, 2008, 2009, 2019 Free Software Foundation, Inc. ;; Author: William Xu <william.xwl@gmail.com>, Yoni Rabkin (yrk@gnu.org) ;; 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, 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: ;; Display playing time on mode line, it looks like: 01:32/04:09. ;; Put this file into your load-path and the following into your ;; ~/.emacs: ;; (require 'emms-playing-time) ;; (emms-playing-time 1) ;; Note: `(emms-playing-time -1)' will disable emms-playing-time module ;; completely, and is not recommended. (since some other emms modules ;; may rely on it, such as `emms-lastfm.el') ;; Instead, to toggle displaying playing time on mode line, one could ;; call `emms-playing-time-enable-display' and ;; `emms-playing-time-disable-display'." ;;; Code: (require 'cl-lib) (require 'emms-info) (require 'emms-player-simple) ;;; Customizations (defgroup emms-playing-time nil "Playing-time module for EMMS." :group 'emms) (defcustom emms-playing-time-display-short-p nil "Non-nil will only display elapsed time. e.g., display 02:37 instead of 02:37/05:49." :type 'boolean :group 'emms-playing-time) (defcustom emms-playing-time-display-format " %s " "Format used for displaying playing time." :type 'string :group 'emms-playing-time) (defcustom emms-playing-time-style 'time "Style used for displaying playing time. Valid styles are `time' (e.g., 01:30/4:20), `bar' (e.g., [===> ]), and `downtime' (e.g. -03:58)." :type 'symbol :group 'emms-playing-time) ;;; Emms Playing Time (defvar emms-playing-time-display-p nil "Whether to display playing time on mode line or not") (defvar emms-playing-time 0 "Time elapsed in current track.") (defvar emms-playing-time-string "") (defvar emms-playing-time-display-timer nil) (defvar emms-playing-time-p nil "Whether emms-playing-time module is enabled or not") (defun emms-playing-time-start () "Get ready for display playing time." (setq emms-playing-time 0) (unless emms-playing-time-display-timer (setq emms-playing-time-display-timer (run-at-time t 1 'emms-playing-time-display)))) (defun emms-playing-time-stop () "Remove playing time on the mode line." (if (or (not emms-player-paused-p) emms-player-stopped-p) (progn (setq emms-playing-time-string "") (force-mode-line-update))) (emms-cancel-timer emms-playing-time-display-timer) (setq emms-playing-time-display-timer nil)) (defun emms-playing-time-pause () "Pause playing time." (if emms-player-paused-p (emms-playing-time-stop) (unless emms-playing-time-display-timer (setq emms-playing-time-display-timer (run-at-time t 1 'emms-playing-time-display))))) (defun emms-playing-time-seek (sec) "Seek forward or backward SEC playing time." (setq emms-playing-time (+ emms-playing-time sec)) (when (< emms-playing-time 0) ; back to start point (setq emms-playing-time 0))) (defun emms-playing-time-set (sec) "Set the playing time to SEC." (setq emms-playing-time sec) (when (< emms-playing-time 0) ; back to start point (setq emms-playing-time 0))) (defun emms-playing-time (arg) "Turn on emms playing time if ARG is positive, off otherwise. Note: `(emms-playing-time -1)' will disable emms-playing-time module completely, and is not recommended. (since some other emms modules may rely on it, such as `emms-lastfm.el') Instead, to toggle displaying playing time on mode line, one could call `emms-playing-time-enable-display' and `emms-playing-time-disable-display'." (if (and arg (> arg 0)) (progn (setq emms-playing-time-p t emms-playing-time-display-p t) (emms-playing-time-mode-line) (add-hook 'emms-player-started-hook 'emms-playing-time-start) (add-hook 'emms-player-stopped-hook 'emms-playing-time-stop) (add-hook 'emms-player-finished-hook 'emms-playing-time-stop) (add-hook 'emms-player-paused-hook 'emms-playing-time-pause) (add-hook 'emms-player-seeked-functions 'emms-playing-time-seek) (add-hook 'emms-player-time-set-functions 'emms-playing-time-set)) (setq emms-playing-time-p nil emms-playing-time-display-p nil) (emms-playing-time-stop) (emms-playing-time-restore-mode-line) (remove-hook 'emms-player-started-hook 'emms-playing-time-start) (remove-hook 'emms-player-stopped-hook 'emms-playing-time-stop) (remove-hook 'emms-player-finished-hook 'emms-playing-time-stop) (remove-hook 'emms-player-paused-hook 'emms-playing-time-pause) (remove-hook 'emms-player-seeked-functions 'emms-playing-time-seek) (remove-hook 'emms-player-time-set-functions 'emms-playing-time-set))) ;;;###autoload (defun emms-playing-time-enable-display () "Display playing time on mode line." (interactive) (setq emms-playing-time-display-p t)) ;;;###autoload (defun emms-playing-time-disable-display () "Remove playing time from mode line." (interactive) (setq emms-playing-time-display-p nil)) (defun emms-playing-time-display () "Display playing time on the mode line." (setq emms-playing-time (round (1+ emms-playing-time))) (setq emms-playing-time-string "") (when emms-playing-time-display-p (let* ((min (/ emms-playing-time 60)) (sec (% emms-playing-time 60)) (total-playing-time (or (emms-track-get (emms-playlist-current-selected-track) 'info-playing-time) 0)) (total-min-only (/ total-playing-time 60)) (total-sec-only (% total-playing-time 60))) (cl-case emms-playing-time-style ((downtime) ; `downtime' style (setq emms-playing-time-string (emms-replace-regexp-in-string " " "0" (if (or emms-playing-time-display-short-p ;; unable to get total playing-time (eq total-playing-time 0)) (format "%2d:%2d" min sec) (format "-%2d:%2d" (/ (- total-playing-time emms-playing-time) 60) (% (- total-playing-time sec) 60)))))) ((bar) ; `bar' style (if (zerop total-playing-time) (setq emms-playing-time-string "[==>........]") (let ((progress "[") ;; percent based on 10 (percent (/ (* emms-playing-time 10) total-playing-time))) (dotimes (i percent) (setq progress (concat progress "="))) (setq progress (concat progress ">")) (dotimes (i (- 10 percent)) (setq progress (concat progress " "))) (setq progress (concat progress "]")) (setq emms-playing-time-string progress)))) (t ; `time' style (setq emms-playing-time-string (emms-replace-regexp-in-string " " "0" (if (or emms-playing-time-display-short-p ;; unable to get total playing-time (eq total-playing-time 0)) (format "%2d:%2d" min sec) (format "%2d:%2d/%2s:%2s" min sec total-min-only total-sec-only)))))) (setq emms-playing-time-string (format emms-playing-time-display-format emms-playing-time-string)))) (force-mode-line-update)) (defun emms-playing-time-mode-line () "Add playing time to the mode line." (or global-mode-string (setq global-mode-string '(""))) (unless (member 'emms-playing-time-string global-mode-string) (setq global-mode-string (append global-mode-string '(emms-playing-time-string))))) (defun emms-playing-time-restore-mode-line () "Restore the mode line." (setq global-mode-string (remove 'emms-playing-time-string global-mode-string)) (force-mode-line-update)) (provide 'emms-playing-time) ;;; emms-playing-time.el ends here �������������������emms-6.00/emms-playlist-limit.el��������������������������������������������������������������������0000664�0001750�0001750�00000020645�13746063641�015055� 0����������������������������������������������������������������������������������������������������ustar �yrk�����������������������������yrk��������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������;;; emms-playlist-limit.el --- Limit playlist by various info -*- lexical-binding: t -*- ;; Copyright (C) 2018 Free Software Foundation, Inc. ;; Author: William Xu <william.xwl@gmail.com> ;; Author: Fran Burstall <fran.burstall@gmail.com> ;; Keywords: emms, limit ;; 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, 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; see the file COPYING. If not, write to the ;; Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, ;; Boston, MA 02110-1301, USA. ;;; Commentary: ;; This code allows you to "limit" a playlist in the current buffer ;; by creating, and switching to, a derived playlist containing only ;; those tracks with a type (info-artist and the like) matching a ;; regexp. ;; If the current buffer is the current playlist then the derived ;; playlist is made current. ;; Usage: ;; ------------------------------------------------------------------ ;; This code is activated by (emms-all). Otherwise simply do: ;; (require 'emms-playlist-limit) ;; Key bindings ;; ------------------------------------------------------------------ ;; / / emms-playlist-limit-to-all ;; / a emms-playlist-limit-to-info-artist ;; / b emms-playlist-limit-to-info-album ;; / c emms-playlist-limit-to-info-composer ;; / d emms-playlist-limit-to-description ;; / g emms-playlist-limit-to-info-genre ;; / n emms-playlist-limit-to-name ;; / p emms-playlist-limit-to-info-performer ;; / t emms-playlist-limit-to-info-title ;; / y emms-playlist-limit-to-info-year ;;; Code: (require 'seq) (require 'emms-playlist-mode) ;; User Interfaces (defgroup emms-playlist-limit nil "Playlist limit module for EMMS." :group 'emms) (defcustom emms-playlist-limit-hook nil "Hooks to run after each limit operation." :type 'symbol :group 'emms-playlist-limit) (defmacro define-emms-playlist-limit (attribute) "Macro for defining emms playlist limit to ATTRIBUTE function." `(defun ,(intern (format "emms-playlist-limit-to-%s" attribute)) (regexp) ,(format "Switch to a playlist comprising tracks with %s matching REGEXP. REGEXP defaults to the value of %s for the track at point. When the current buffer is the current playlist, make the derived playlist the current playlist." attribute attribute) (interactive (list (let* ((curr (or (emms-playlist-limit-track-get (or (emms-playlist-track-at) (emms-playlist-track-at (max 1 (1- (point))))) ; at eol (quote ,attribute)) (emms-playlist-limit-track-get (emms-playlist-selected-track) (quote ,attribute)))) (attr-name ,(emms-replace-regexp-in-string "info-" "" (symbol-name attribute))) (fmt (if curr (format "Limit to %s (regexp = %s): " attr-name curr) (format "Limit to %s (regexp): " attr-name)))) (read-string fmt)))) (when (string= regexp "") (setq regexp (or (emms-playlist-limit-track-get (or (emms-playlist-track-at) (emms-playlist-track-at (max 1 (1- (point))))) ; at eol (quote ,attribute)) (emms-playlist-limit-track-get (emms-playlist-selected-track) (quote ,attribute))))) (if regexp (emms-playlist-limit-do (quote ,attribute) regexp) (message "Limit cancelled: no regexp.")))) (define-emms-playlist-limit info-artist) (define-emms-playlist-limit info-composer) (define-emms-playlist-limit info-performer) (define-emms-playlist-limit info-title) (define-emms-playlist-limit info-album) (define-emms-playlist-limit info-year) (define-emms-playlist-limit info-genre) (define-emms-playlist-limit name) (define-emms-playlist-limit description) (defvar-local emms-playlist-limit--original-playlist nil "Playlist buffer from which we derive the limited playlist.") (defun emms-playlist-limit-to-all () "Switch to playlist from which this playlist was derived (if it still exists) and bury this playlist. If this playlist is current, make the playlist we switch to current." (interactive) (when (and emms-playlist-limit--original-playlist (buffer-live-p emms-playlist-limit--original-playlist)) (let* ((old-buf (current-buffer)) (old-buf-is-current-playlist (eq old-buf emms-playlist-buffer))) (switch-to-buffer emms-playlist-limit--original-playlist) (when old-buf-is-current-playlist (emms-playlist-set-playlist-buffer)) (bury-buffer old-buf)))) (define-key emms-playlist-mode-map (kbd "/ n") 'emms-playlist-limit-to-name) (define-key emms-playlist-mode-map (kbd "/ a") 'emms-playlist-limit-to-info-artist) (define-key emms-playlist-mode-map (kbd "/ c") 'emms-playlist-limit-to-info-composer) (define-key emms-playlist-mode-map (kbd "/ p") 'emms-playlist-limit-to-info-performer) (define-key emms-playlist-mode-map (kbd "/ t") 'emms-playlist-limit-to-info-title) (define-key emms-playlist-mode-map (kbd "/ b") 'emms-playlist-limit-to-info-album) (define-key emms-playlist-mode-map (kbd "/ y") 'emms-playlist-limit-to-info-year) (define-key emms-playlist-mode-map (kbd "/ g") 'emms-playlist-limit-to-info-genre) (define-key emms-playlist-mode-map (kbd "/ d") 'emms-playlist-limit-to-description) (define-key emms-playlist-mode-map (kbd "/ /") 'emms-playlist-limit-to-all) ;;; Low Level Functions (defun emms-playlist-limit-track-get (track type) "Return the value of TYPE from TRACK. Here TYPE is a field available to `emms-track-get' or 'description which gives the result of `emms-track-description-function'. When type is 'info-year, also tries 'info-originalyear, 'info-originaldate and 'info-date to get a usable date." (cond ((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)))) (or (emms-format-date-to-year date) "<unknown year>"))) ((eq type 'description) (funcall emms-track-description-function track)) (t (emms-track-get track type)))) (defun emms-playlist-limit--derive-playlist (playlist pred name) "Return a new playlist NAME of tracks in PLAYLIST for which (PRED track) is non-nil." (let* ((tracks (nreverse (with-current-buffer playlist (save-excursion (emms-playlist-tracks-in-region (point-min) (point-max)))))) (filtered-tracks (seq-filter pred tracks)) (new-playlist (or (get-buffer name) (emms-playlist-new name)))) (with-current-buffer new-playlist (emms-with-inhibit-read-only-t (erase-buffer)) (mapc #'emms-playlist-insert-track filtered-tracks)) new-playlist)) (defun emms-playlist-limit--limit-playlist (playlist type regexp) "Return a new playlist of tracks in PLAYLIST with TYPE matching REGEXP." (let* ((bufname (concat (buffer-name playlist) (format "/%s=%s" (emms-replace-regexp-in-string "info-" "" (symbol-name type)) regexp)))) (emms-playlist-limit--derive-playlist playlist `(lambda (track) (let ((field (emms-playlist-limit-track-get track (quote ,type)))) (and field (string-match ,regexp field)))) bufname))) (defun emms-playlist-limit-do (type regexp) "Switch to a derived playlist containing the tracks with TYPE matching REGEXP. e.g., (emms-playlist-limit-do 'info-artist \"Jane Zhang\") See `emms-info-mp3find-arguments' for possible options for TYPE." (emms-playlist-ensure-playlist-buffer) (let* ((curr (emms-playlist-selected-track)) (old-buf (current-buffer)) (old-buf-is-current-playlist (eq old-buf emms-playlist-buffer)) (buf (emms-playlist-limit--limit-playlist old-buf type regexp))) (with-current-buffer buf (if (= (point-min) (point-max)) (progn (message "No matching tracks found!") (kill-buffer)) (let ((pos (when curr (text-property-any (point-min) (point-max) 'emms-track curr)))) (if pos (emms-playlist-select pos) (emms-playlist-select-first))) (emms-playlist-mode-center-current) (setq emms-playlist-limit--original-playlist old-buf) (when old-buf-is-current-playlist (emms-playlist-set-playlist-buffer)) (run-hooks 'emms-playlist-limit-hook) (switch-to-buffer buf))))) (provide 'emms-playlist-limit) ;;; emms-playlist-limit.el ends here �������������������������������������������������������������������������������������������emms-6.00/emms-playlist-mode.el���������������������������������������������������������������������0000664�0001750�0001750�00000052371�13746063641�014664� 0����������������������������������������������������������������������������������������������������ustar �yrk�����������������������������yrk��������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������;;; emms-playlist-mode.el --- Playlist mode for Emms. ;; Copyright (C) 2005-2019 Free Software Foundation, Inc. ;; Author: Yoni Rabkin <yrk@gnu.org> ;; 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, 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 is a method of displaying and manipulating the different Emms ;;; playlist buffers. ;;; ;;; Emms developer's motto: "When forcer says (require 'jump) we say ;;; (funcall #'jump height)" ;;; Code: ;;; -------------------------------------------------------- ;;; Variables ;;; -------------------------------------------------------- (require 'emms) (condition-case nil (require 'overlay) (error nil)) (require 'emms-source-playlist) (defvar emms-playlist-mode-hook nil "Emms playlist mode hook.") (defvar emms-playlist-mode-selected-overlay nil "Last selected track. Use for updating the display.") (defvar emms-playlist-mode-switched-buffer nil "Last buffer visited before calling `emms-playlist-mode-switch-buffer'.") (defvar emms-playlist-mode-popup-enabled nil "True when the playlist was called as a popup window.") (defvar emms-playlist-mode-kill-whole-line-p t "When true line kills behave like a typical music player.") (make-variable-buffer-local 'emms-playlist-mode-selected-overlay) (defgroup emms-playlist-mode nil "*The Emacs Multimedia System playlist mode." :prefix "emms-playlist-mode-" :group 'emms) (defcustom emms-playlist-mode-open-playlists nil "*Determine whether to open playlists in a new EMMS buffer on RET. This is useful if you have a master playlist buffer that is composed of other playlists." :type 'boolean :group 'emms-playlist-mode) (defcustom emms-playlist-mode-window-width 25 "*Determine the width of the Emms popup window. The value should a positive integer." :type 'integer :group 'emms-playlist-mode) (defcustom emms-playlist-mode-center-when-go nil "*Determine whether to center on the currently selected track. This is true for every invocation of `emms-playlist-mode-go'." :type 'boolean :group 'emms-playlist-mode) ;;; -------------------------------------------------------- ;;; Faces ;;; -------------------------------------------------------- (defface emms-playlist-track-face '((((class color) (background dark)) (:foreground "DarkSeaGreen")) (((class color) (background light)) (:foreground "Blue")) (((type tty) (class mono)) (:inverse-video t)) (t (:background "Blue"))) "Face for the tracks in a playlist buffer." :group 'emms-playlist-mode) (defface emms-playlist-selected-face '((((class color) (background dark)) (:foreground "SteelBlue3")) (((class color) (background light)) (:background "blue3" :foreground "white")) (((type tty) (class mono)) (:inverse-video t)) (t (:background "blue3"))) "Face for highlighting the selected track." :group 'emms-playlist-mode) ;;; -------------------------------------------------------- ;;; Keys ;;; -------------------------------------------------------- (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) (define-key map (kbd "C-y") 'emms-playlist-mode-yank) (define-key map (kbd "C-k") 'emms-playlist-mode-kill-track) (define-key map (kbd "C-w") 'emms-playlist-mode-kill) (define-key map (kbd "C-_") 'emms-playlist-mode-undo) (define-key map (kbd "C-/") 'emms-playlist-mode-undo) (define-key map (kbd "C-x u") 'emms-playlist-mode-undo) (define-key map (kbd "C-n") 'next-line) (define-key map (kbd "C-p") 'previous-line) (define-key map (kbd "C-j") 'emms-playlist-mode-insert-newline) (define-key map (kbd "M-y") 'emms-playlist-mode-yank-pop) (define-key map (kbd "M-<") 'emms-playlist-mode-first) (define-key map (kbd "M->") 'emms-playlist-mode-last) (define-key map (kbd "M-n") 'emms-playlist-mode-next) (define-key map (kbd "M-p") 'emms-playlist-mode-previous) (define-key map (kbd "a") 'emms-playlist-mode-add-contents) (define-key map (kbd "b") 'emms-playlist-set-playlist-buffer) (define-key map (kbd "D") 'emms-playlist-mode-kill-track) (define-key map (kbd "n") 'emms-next) (define-key map (kbd "p") 'emms-previous) (define-key map (kbd "SPC") 'scroll-up) (define-key map (kbd ">") 'emms-seek-forward) (define-key map (kbd "<") 'emms-seek-backward) (define-key map (kbd "P") 'emms-pause) (define-key map (kbd "s") 'emms-stop) (define-key map (kbd "f") 'emms-show) (define-key map (kbd "c") 'emms-playlist-mode-center-current) (define-key map (kbd "q") 'emms-playlist-mode-bury-buffer) (define-key map (kbd "K") 'emms-playlist-mode-current-kill) (define-key map (kbd "?") 'describe-mode) (define-key map (kbd "r") 'emms-random) (define-key map (kbd "C") 'emms-playlist-clear) (define-key map (kbd "d") 'emms-playlist-mode-goto-dired-at-point) (define-key map (kbd "<mouse-2>") 'emms-playlist-mode-play-current-track) (define-key map (kbd "RET") 'emms-playlist-mode-play-smart) map) "Keymap for `emms-playlist-mode'.") (defmacro emms-playlist-mode-move-wrapper (name fun) "Create a function NAME which is an `interactive' version of FUN. NAME should be a symbol. FUN should be a function." `(defun ,name () ,(format "Interactive wrapper around `%s' for playlist-mode." fun) (interactive) (,fun))) (emms-playlist-mode-move-wrapper emms-playlist-mode-first emms-playlist-first) (emms-playlist-mode-move-wrapper emms-playlist-mode-select-next emms-playlist-next) (emms-playlist-mode-move-wrapper emms-playlist-mode-select-previous emms-playlist-previous) (defun emms-playlist-mode-bury-buffer () "Wrapper around `bury-buffer' for popup windows." (interactive) (if emms-playlist-mode-popup-enabled (unwind-protect (delete-window) (setq emms-playlist-mode-popup-enabled nil)) (bury-buffer))) (defun emms-playlist-mode-current-kill () "If the current buffer is an EMMS playlist buffer, kill it. Otherwise, kill the current EMMS playlist buffer." (interactive) (if (and emms-playlist-buffer-p (not (eq (current-buffer) emms-playlist-buffer))) (kill-buffer (current-buffer)) (emms-playlist-current-kill))) (defun emms-playlist-mode-last () "Move to directly after the last track in the current buffer." (interactive) (emms-playlist-ensure-playlist-buffer) (let ((last (condition-case nil (save-excursion (goto-char (point-max)) (point)) (error nil)))) (if last (goto-char last) (error "No last track")))) (defun emms-playlist-mode-center-current () "Move point to the currently selected track." (interactive) (goto-char (if emms-playlist-mode-selected-overlay (overlay-start emms-playlist-mode-selected-overlay) (point-min)))) (defun emms-playlist-mode-play-current-track () "Start playing track at point." (interactive) (emms-playlist-set-playlist-buffer (current-buffer)) (unless (emms-playlist-track-at (point)) (emms-playlist-next)) (emms-playlist-select (point)) (when emms-player-playing-p (emms-stop)) (emms-start)) (defun emms-playlist-mode-play-smart () "Determine the best operation to take on the current track. If on a playlist, and `emms-playlist-mode-open-playlists' is non-nil, load the playlist at point into a new buffer. Otherwise play the track immediately." (interactive) (save-excursion ;; move to the start of the line, in case the point is on the \n, ;; which isn't propertized (emms-move-beginning-of-line nil) (if (not emms-playlist-mode-open-playlists) (emms-playlist-mode-play-current-track) (unless (emms-playlist-track-at) (emms-playlist-next)) (let* ((track (emms-playlist-track-at)) (name (emms-track-get track 'name)) (type (emms-track-get track 'type))) (if (or (eq type 'playlist) (and (eq type 'file) (string-match "\\.\\(m3u\\|pls\\)\\'" name))) (emms-playlist-mode-load-playlist) (emms-playlist-mode-play-current-track)))))) (defun emms-playlist-mode-switch-buffer () "Switch to the playlist buffer and then switch back if called again. This function switches to the current Emms playlist buffer and remembers the buffer switched from. When called again the function switches back to the remembered buffer." (interactive) (if (eq (current-buffer) emms-playlist-buffer) (switch-to-buffer emms-playlist-mode-switched-buffer) (setq emms-playlist-mode-switched-buffer (current-buffer)) (switch-to-buffer emms-playlist-buffer))) (defun emms-playlist-mode-insert-newline () "Insert a newline at point." (interactive) (emms-with-inhibit-read-only-t (newline))) (defun emms-playlist-mode-undo () "Wrapper around `undo'." (interactive) (emms-with-inhibit-read-only-t (undo))) (defun emms-playlist-mode-add-contents () "Add files in the playlist at point to the current playlist buffer. If we are in the current playlist, make a new playlist buffer and set it as current." (interactive) (save-excursion (emms-move-beginning-of-line nil) (unless (emms-playlist-track-at) (emms-playlist-next)) (let* ((track (emms-playlist-track-at)) (name (emms-track-get track 'name)) (type (emms-track-get track 'type)) (playlist-p (or (eq type 'playlist) (and (eq type 'file) (save-match-data (string-match "\\.\\(m3u\\|pls\\)\\'" name)))))) (emms-playlist-select (point)) (unless (and (buffer-live-p emms-playlist-buffer) (not (eq (current-buffer) emms-playlist-buffer))) (setq emms-playlist-buffer (emms-playlist-set-playlist-buffer (emms-playlist-new)))) (with-current-emms-playlist (goto-char (point-max)) (when playlist-p (insert (emms-track-force-description track) "\n")) (let ((beg (point))) (if playlist-p (emms-add-playlist name) (let ((func (intern (concat "emms-add-" (symbol-name type))))) (if (functionp func) (funcall func name) ;; fallback (emms-add-file name)))) (when playlist-p (goto-char (point-max)) (while (progn (forward-line -1) (>= (point) beg)) (insert " "))) (goto-char (point-min)) (message "Added %s" (symbol-name type))))))) (defun emms-playlist-mode-goto-dired-at-point () "Visit the track at point in a `dired' buffer." (interactive) (let ((track (emms-playlist-track-at))) (if track (let ((name (emms-track-get track 'name)) (type (emms-track-get track 'type))) (if (eq type 'file) (dired (file-name-directory name)) (error "Can't visit this track type in Dired"))) (error "No track at point")))) ;;; -------------------------------------------------------- ;;; Killing and yanking ;;; -------------------------------------------------------- (defun emms-playlist-mode-between-p (p a b) "Return t if P is a point between points A and B." (and (<= a p) (<= p b))) ;; D (defun emms-playlist-mode-kill-entire-track () "Kill track at point, including newline." (interactive) (let ((kill-whole-line t)) (emms-playlist-mode-kill-track))) ;; C-k (defun emms-playlist-mode-kill-track () "Kill track at point." (interactive) (emms-with-inhibit-read-only-t (let ((track (emms-playlist-track-at))) (when track (let ((track-region (emms-property-region (point) 'emms-track))) (when (and emms-player-playing-p (emms-playlist-selected-track-at-p)) (emms-stop) (delete-overlay emms-playlist-mode-selected-overlay) (setq emms-playlist-mode-selected-overlay nil)))) (let ((kill-whole-line emms-playlist-mode-kill-whole-line-p)) (goto-char (point-at-bol)) (kill-line))))) ;; C-w (defun emms-playlist-mode-kill () "Kill from mark to point." (interactive) (emms-with-inhibit-read-only-t ;; Are we killing the playing/selected track? (when (and (markerp emms-playlist-selected-marker) (emms-playlist-mode-between-p (marker-position emms-playlist-selected-marker) (region-beginning) (region-end))) (emms-stop) (delete-overlay emms-playlist-mode-selected-overlay) (setq emms-playlist-mode-selected-overlay nil)) (kill-region (region-beginning) (region-end)))) (defun emms-playlist-mode-correct-previous-yank () "Fix the previous yank if needed." (when (and (< (point-at-bol) (point)) (< (point) (point-at-eol))) (newline))) ;; C-y (defun emms-playlist-mode-yank () "Yank into the playlist buffer." (interactive) (emms-with-inhibit-read-only-t (goto-char (point-at-bol)) (yank) (emms-playlist-mode-correct-previous-yank))) ;; M-y (defun emms-playlist-mode-yank-pop () "Cycle through the kill-ring." (interactive) (emms-with-inhibit-read-only-t (yank-pop nil) (emms-playlist-mode-correct-previous-yank))) ;;; -------------------------------------------------------- ;;; Overlay ;;; -------------------------------------------------------- (defun emms-playlist-mode-overlay-selected () "Place an overlay over the currently selected track." (when emms-playlist-selected-marker (save-excursion (goto-char emms-playlist-selected-marker) (let ((reg (emms-property-region (point) 'emms-track))) (if emms-playlist-mode-selected-overlay (move-overlay emms-playlist-mode-selected-overlay (car reg) (cdr reg)) (setq emms-playlist-mode-selected-overlay (make-overlay (car reg) (cdr reg) nil t nil)) (overlay-put emms-playlist-mode-selected-overlay 'face 'emms-playlist-selected-face) (overlay-put emms-playlist-mode-selected-overlay 'evaporate t)))))) ;;; -------------------------------------------------------- ;;; Saving/Restoring ;;; -------------------------------------------------------- (defun emms-playlist-mode-open-buffer (filename) "Opens a previously saved playlist buffer. It creates a buffer called \"filename\", and restores the contents of the saved playlist inside." (interactive "fFile: ") (let* ((s) (buffer (get-buffer-create filename)) (name (buffer-name buffer))) (with-current-buffer buffer (emms-insert-file-contents filename) (setq s (read (buffer-string)))) (kill-buffer buffer) (with-current-buffer (emms-playlist-new name) (emms-with-inhibit-read-only-t (insert s) (goto-char (point-min)) (emms-walk-tracks (emms-playlist-update-track))) (emms-playlist-first) (emms-playlist-select (point)) (switch-to-buffer (current-buffer))))) (defun emms-playlist-mode-load-playlist () "Load the playlist into a new EMMS buffer. This preserves the current EMMS buffer." (interactive) (let* ((track (emms-playlist-track-at)) (name (emms-track-get track 'name)) (type (emms-track-get track 'type))) (emms-playlist-select (point)) (run-hooks 'emms-player-stopped-hook) (switch-to-buffer (emms-playlist-set-playlist-buffer (emms-playlist-new))) (emms-add-playlist name))) ;;; -------------------------------------------------------- ;;; Local functions ;;; -------------------------------------------------------- (defun emms-playlist-mode-insert-track (track &optional no-newline) "Insert the description of TRACK at point. When NO-NEWLINE is non-nil, do not insert a newline after the track." (emms-playlist-ensure-playlist-buffer) (emms-with-inhibit-read-only-t (insert (emms-propertize (emms-track-force-description track) 'emms-track track 'face 'emms-playlist-track-face)) (when (emms-playlist-selected-track-at-p) (emms-playlist-mode-overlay-selected)) (unless no-newline (insert "\n")))) (defun emms-playlist-mode-update-track-function () "Update the track display at point." (emms-playlist-ensure-playlist-buffer) (emms-with-inhibit-read-only-t (let ((track-region (emms-property-region (point) 'emms-track)) (track (get-text-property (point) 'emms-track)) (selectedp (emms-playlist-selected-track-at-p))) (save-excursion (delete-region (car track-region) (cdr track-region)) (when selectedp (delete-overlay emms-playlist-mode-selected-overlay) (setq emms-playlist-mode-selected-overlay nil)) (emms-playlist-mode-insert-track track t)) (when selectedp (emms-playlist-select (point)))))) ;;; -------------------------------------------------------- ;;; Entry ;;; -------------------------------------------------------- (defun emms-playlist-mode-go () "Switch to the current emms-playlist buffer and use emms-playlist-mode." (interactive) (if (or (null emms-playlist-buffer) (not (buffer-live-p emms-playlist-buffer))) (error "No current Emms buffer") (switch-to-buffer emms-playlist-buffer) (when (and (not (eq major-mode 'emms-playlist-mode)) emms-playlist-buffer-p) (emms-playlist-mode)) (when emms-playlist-mode-center-when-go (emms-playlist-mode-center-current)))) (defun emms () "Switch to the current emms-playlist buffer, use emms-playlist-mode and query for a directory tree to add to the playlist." (interactive) (if (or (null emms-playlist-buffer) (not (buffer-live-p emms-playlist-buffer))) (call-interactively 'emms-add-directory)) (emms-playlist-mode-go)) (defun emms-playlist-mode-go-popup (&optional window-width) "Popup emms-playlist buffer as a side window. Default value for WINDOW-WIDTH is `emms-playlist-mode-window-width'. WINDOW-WIDTH should be a positive integer." (interactive) (setq emms-playlist-mode-window-width (round (or window-width emms-playlist-mode-window-width))) (split-window-horizontally (- emms-playlist-mode-window-width)) (other-window 1) (emms-playlist-mode-go) (setq emms-playlist-mode-popup-enabled t)) (defun emms-playlist-mode-next (arg) "Navigate between playlists." (interactive "p") (let ((playlists (emms-playlist-buffer-list)) bufs idx) (if playlists ;; if not in playlist mode, switch to emms-playlist-buffer (if (not (member (current-buffer) playlists)) (switch-to-buffer (if (and emms-playlist-buffer (buffer-live-p emms-playlist-buffer)) emms-playlist-buffer (car playlists))) (setq bufs (member (current-buffer) playlists)) (setq idx (+ (- (length playlists) (length bufs)) (if (> arg 0) 1 -1))) (switch-to-buffer (nth (mod idx (length playlists)) playlists))) (message "No playlist found!")))) (defun emms-playlist-mode-previous (arg) (interactive "p") (emms-playlist-mode-next (- arg))) (defun emms-playlist-mode-startup () "Instigate emms-playlist-mode on the current buffer." ;; when there is neither a current emms track or a playing one... (when (not (or emms-playlist-selected-marker emms-player-playing-p)) ;; ...then stop the player. (emms-stop) ;; why select the first track? (when emms-playlist-buffer-p (emms-playlist-select-first))) ;; when there is a selected track. (when emms-playlist-selected-marker (emms-playlist-mode-overlay-selected)) (emms-with-inhibit-read-only-t (add-text-properties (point-min) (point-max) '(face emms-playlist-track-face))) (setq buffer-read-only t) (setq truncate-lines t) (setq buffer-undo-list nil)) ;;;###autoload (defun emms-playlist-mode () "A major mode for Emms playlists. \\{emms-playlist-mode-map}" (interactive) (let ((val emms-playlist-buffer-p)) (kill-all-local-variables) (setq emms-playlist-buffer-p val)) (use-local-map emms-playlist-mode-map) (setq major-mode 'emms-playlist-mode mode-name "EMMS") (setq emms-playlist-insert-track-function 'emms-playlist-mode-insert-track) (setq emms-playlist-update-track-function 'emms-playlist-mode-update-track-function) (add-hook 'emms-playlist-selection-changed-hook 'emms-playlist-mode-overlay-selected) (emms-playlist-mode-startup) (run-hooks 'emms-playlist-mode-hook)) (provide 'emms-playlist-mode) ;;; emms-playlist-mode.el ends here �����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������emms-6.00/emms-playlist-sort.el���������������������������������������������������������������������0000664�0001750�0001750�00000020356�13746063641�014725� 0����������������������������������������������������������������������������������������������������ustar �yrk�����������������������������yrk��������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������;;; emms-playlist-sort.el --- sort emms playlist ;; Copyright (C) 2005, 2006, 2007, 2008, 2009, 2018 Free Software Foundation, Inc. ;; Author: William Xu <william.xwl@gmail.com> ;; 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, 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. ;;; Code: (require 'cl-lib) (require 'emms-last-played) (require 'emms-playlist-mode) ;;; User Customizations (defgroup emms-playlist-sort nil "Sorting Emacs Multimedia System playlists." :prefix "emms-playlist-sort-" :group 'emms) (defcustom emms-playlist-sort-list '(info-artist info-album) "Sorting list used by `emms-playlist-sort-by-list'. Currently it understands the following fields: name info-artist imfo-composer info-performer info-title info-album info-genre info-playing-time info-tracknumber info-discnumber." :type 'symbol :group 'emms-playlist-sort) (defcustom emms-playlist-sort-prefix "S" "Prefix key sequence for `emms-playlist-sort-map'. Remember to call `emms-playlist-sort-map-setup' if you modify it." :type 'string :group 'emms-playlist-sort) ;;; User Interfaces (defmacro define-emms-playlist-sort (attribute) "Macro for defining emms playlist sort functions on strings ." `(defun ,(intern (format "emms-playlist-sort-by-%s" attribute)) () ,(format "Sort emms playlist by %s, increasingly. With a prefix argument, decreasingly." attribute) (interactive) (emms-playlist-sort '(lambda (a b) (funcall (if current-prefix-arg 'emms-string> 'emms-string<) (emms-track-get a (quote ,attribute)) (emms-track-get b (quote ,attribute))))))) (define-emms-playlist-sort name) (define-emms-playlist-sort info-artist) (define-emms-playlist-sort info-composer) (define-emms-playlist-sort info-performer) (define-emms-playlist-sort info-title) (define-emms-playlist-sort info-album) (define-emms-playlist-sort info-year) (define-emms-playlist-sort info-note) (defun emms-playlist-sort-by-natural-order () "Sort emms playlist by natural order. See `emms-sort-natural-order-less-p'." (interactive) (emms-playlist-sort 'emms-sort-natural-order-less-p)) (defun emms-playlist-sort-by-list () "Sort emms playlist by `emms-playlist-sort-list'. The sort will be carried out until comparsion succeeds, increasingly." (interactive) (emms-playlist-sort 'emms-playlist-sort-by-list-p)) (defun emms-playlist-sort-by-last-played () "Sort emms playlist by last played time, increasingly. With a prefix argument, decreasingly." (interactive) (emms-playlist-sort '(lambda (a b) (funcall (if current-prefix-arg 'not 'identity) (time-less-p (or (emms-track-get a 'last-played) '(0 0 0)) (or (emms-track-get b 'last-played) '(0 0 0))))))) (defun emms-playlist-sort-by-play-count () "Sort emms playlist by play-count, increasingly. With a prefix argument, decreasingly." (interactive) (emms-playlist-sort '(lambda (a b) (funcall (if current-prefix-arg 'not 'identity) (< (or (emms-track-get a 'play-count) 0) (or (emms-track-get b 'play-count) 0)))))) (defun emms-playlist-sort-by-file-extension () "Sort emms playlist by file extension, increasingly. With a prefix argument, decreasingly." (interactive) (emms-playlist-sort '(lambda (a b) (funcall (if current-prefix-arg 'emms-string> 'emms-string<) (file-name-extension (emms-track-get a 'name)) (file-name-extension (emms-track-get b 'name)))))) (defun emms-playlist-sort-by-file-mtime () "Sort emms playlist by file mtime, newest first. With a prefix argument, oldest first." (interactive) (emms-playlist-sort '(lambda (a b) (funcall (if current-prefix-arg 'time-less-p (lambda (t1 t2) (not (time-less-p t1 t2)))) (emms-info-track-file-mtime a) (emms-info-track-file-mtime b))))) (defvar emms-playlist-sort-map nil) (defun emms-playlist-sort-map-setup () "Setup sort map with latest `emms-playlist-sort-prefix'." (setq emms-playlist-sort-map (let ((map (make-sparse-keymap))) (define-key map (kbd "n") 'emms-playlist-sort-by-natural-order) (define-key map (kbd "a") 'emms-playlist-sort-by-info-artist) (define-key map (kbd "c") 'emms-playlist-sort-by-play-count) (define-key map (kbd "b") 'emms-playlist-sort-by-info-album) (define-key map (kbd "l") 'emms-playlist-sort-by-last-played) (define-key map (kbd "t") 'emms-playlist-sort-by-info-title) (define-key map (kbd "e") 'emms-playlist-sort-by-file-extension) (define-key map (kbd "p") 'emms-playlist-sort-by-info-performer) (define-key map (kbd "y") 'emms-playlist-sort-by-info-year) (define-key map (kbd "o") 'emms-playlist-sort-by-info-note) (define-key map (kbd "C") 'emms-playlist-sort-by-info-composer) (define-key map (kbd "L") 'emms-playlist-sort-by-list) (define-key map (kbd "N") 'emms-playlist-sort-by-name) (define-key map (kbd "T") 'emms-playlist-sort-by-file-mtime) map)) (define-key emms-playlist-mode-map emms-playlist-sort-prefix emms-playlist-sort-map)) (setq emms-playlist-sort-map (emms-playlist-sort-map-setup)) ;;; Low Level Functions (defun emms-playlist-sort (predicate) "Sort the playlist buffer by PREDICATE." (emms-with-inhibit-read-only-t (emms-playlist-ensure-playlist-buffer) (let ((current (emms-playlist-selected-track)) (tracks (nreverse (emms-playlist-tracks-in-region (point-min) (point-max))))) (delete-region (point-min) (point-max)) (run-hooks 'emms-playlist-cleared-hook) (mapc 'emms-playlist-insert-track (sort tracks predicate)) (let ((pos (when current (text-property-any (point-min) (point-max) 'emms-track current)))) (if pos (emms-playlist-select pos) (emms-playlist-first))) (goto-char (point-min))))) (defun emms-sort-natural-order-less-p (a b) "Sort two tracks by natural order. This is the order in which albums where intended to be played. ie. by album name and then by track number." (let ((album-a (emms-track-get a 'info-album)) (album-b (emms-track-get b 'info-album)) (discnum-a (string-to-number (or (emms-track-get a 'info-discnumber) "0"))) (discnum-b (string-to-number (or (emms-track-get b 'info-discnumber) "0"))) (tracknum-a (string-to-number (or (emms-track-get a 'info-tracknumber) "0"))) (tracknum-b (string-to-number (or (emms-track-get b 'info-tracknumber) "0")))) (or (emms-string< album-a album-b) (and album-a album-b (string= album-a album-b) (or (< discnum-a discnum-b) (and (= discnum-a discnum-b) (< tracknum-a tracknum-b))))))) (defun emms-playlist-sort-by-list-p (a b) (catch 'return (dolist (info emms-playlist-sort-list) (cl-case info ((name info-artist info-composer info-performer info-title info-album info-genre) (when (emms-string< (emms-track-get a info) (emms-track-get b info)) (throw 'return t))) ((info-playing-time) (when (< (emms-track-get a info) (emms-track-get b info)) (throw 'return t))) ((info-tracknumber info-discnumber) (when (< (string-to-number (or (emms-track-get a info) "0")) (string-to-number (or (emms-track-get b info) "0"))) (throw 'return t))))))) (defun emms-string< (s1 s2) (string< (downcase (or s1 "")) (downcase (or s2 "")))) (defun emms-string> (s1 s2) (let ((a (downcase (or s1 ""))) (b (downcase (or s2 "")))) (not (or (string= a b) (string< a b))))) (provide 'emms-playlist-sort) ;;; emms-playlist-sort.el ends here ����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������emms-6.00/emms-print-metadata.1���������������������������������������������������������������������0000664�0001750�0001750�00000002312�13746063641�014541� 0����������������������������������������������������������������������������������������������������ustar �yrk�����������������������������yrk��������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������.\" Hey, EMACS: -*- nroff -*- .\" First parameter, NAME, should be all caps .\" Second parameter, SECTION, should be 1-8, maybe w/ subsection .\" other parameters are allowed: see man(7), man(1) .TH EMMS-PRINT-METADATA 1 "April 29, 2006" EMMS .\" Please adjust this date whenever revising the manpage. .\" .\" Some roff macros, for reference: .\" .nh disable hyphenation .\" .hy enable hyphenation .\" .ad l left justify .\" .ad b justify to both left and right margins .\" .nf disable filling .\" .fi enable filling .\" .br insert line break .\" .sp <n> insert n+1 empty lines .\" for manpage-specific macros, see man(7) .SH NAME emms-print-metadata \- Print information about music files .SH SYNOPSIS .B emms-print-metadata .RI file.ext .br .SH DESCRIPTION .\" TeX users may be more comfortable with the \fB<whatever>\fP and .\" \fI<whatever>\fP escape sequences to invoke bold face and italics, .\" respectively. \fBemms-print-metadata\fP will print metadata about music files to stdout, to be used primarily by EMMS, the Emacs MultiMedia System. .SH SEE ALSO .BR emms (info) .br .SH AUTHOR emms-print-metadata was written by Trent Buck. ����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������emms-6.00/emms-score.el�����������������������������������������������������������������������������0000664�0001750�0001750�00000021371�13746063641�013210� 0����������������������������������������������������������������������������������������������������ustar �yrk�����������������������������yrk��������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������;;; emms-score.el --- Scoring system for mp3player ;; Copyright (C) 2003, 2004, 2005, 2006, 2007, 2008, ;; 2009, 2018 Free Software Foundation, Inc. ;; Authors: Jean-Philippe Theberge <jphiltheberge@videotron.ca>, ;; Yoni Rabkin <yrk@gnu.org> ;; ;; Keywords: emms, mp3, mpeg, multimedia ;; 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, 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; see the file COPYING. If not, write to the ;; Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, ;; Boston, MA 02110-1301, USA. ;;; Commentary: ;; NOTE: This is experimental stuff - comments welcome! There ;; shouldn't worky anything in that file... scores aren't saved, they ;; even don't have any consequence on playing order and there's just ;; one mood in the moment. But it's a beginning and you can score down ;; or up tracks... :) ;; ;; * How to use scoring in emms ;; ;; When you load emms, you are set to a default mood ;; 'emms-default-mood' A mood is a one word string describing how ;; you feel (like "funny", "tired", "aggresive"...) Each mood have is ;; own set of scoring rules. ;; ;; You can change your mood with M-x emms-score-change-mood. ;; ;; Every music file start with a default score of 0 the command ;; emms-score-up-playing and emms-score-down-playing modify the ;; score of the file you are curently listening by 1 In addition, ;; skipping a file (with emms-skip) automaticaly score the file ;; down. ;; ;; With scoring on (this mean the variable emms-use-scoring is t), ;; emms will compare the score of the file with your tolerance to ;; decide if it is played or not. ;; ;; The default tolerance level is 0 (or the variable ;; emms-score-min-score). This mean files with a score of 0 or more will ;; be played and files with a score of -1 or less will be skipped. ;; ;; You can change the tolerance (by 1) with M-x ;; emms-score-lower-tolerance and M-x ;; emms-score-be-more-tolerant ;;; Code: (require 'emms) (defvar emms-scores-list nil) (defvar emms-score-current-mood 'default) (defvar emms-score-min-score 0) (defvar emms-score-default-score 0) (defvar emms-score-hash (make-hash-table :test 'equal)) (defvar emms-score-enabled-p nil "If non-nil, emms score is active.") (defcustom emms-score-file (concat (file-name-as-directory emms-directory) "scores") "*Directory to store the score file." :type 'directory :group 'emms) ;;; User Interfaces (defun emms-score (arg) "Turn on emms-score if prefix argument ARG is a positive integer, off otherwise." (interactive "p") (if (and arg (> arg 0)) (progn (setq emms-score-enabled-p t) (emms-score-load-hash) (setq emms-ok-track-function 'emms-score-ok-track-function) (unless noninteractive (add-hook 'kill-emacs-hook 'emms-score-save-hash))) (setq emms-score-enabled-p nil) (emms-score-save-hash) (setq emms-ok-track-function 'emms-default-ok-track-function) (remove-hook 'kill-emacs-hook 'emms-score-save-hash))) ;;;###autoload (defun emms-score-enable () "Turn on emms-score." (interactive) (emms-score 1) (message "emms score enabled")) ;;;###autoload (defun emms-score-disable () "Turn off emms-score." (interactive) (emms-score -1) (message "emms score disabled")) ;;;###autoload (defun emms-score-toggle () "Toggle emms-score." (interactive) (if emms-score-enabled-p (emms-score-disable) (emms-score-enable))) (defun emms-score-change-mood (mood) "Change the current MOOD. The score hash is automatically saved." (interactive "sMood: ") (emms-score-save-hash) (setq emms-score-current-mood (intern (downcase mood)))) (defun emms-score-up-playing () (interactive) (if emms-player-playing-p (emms-score-change-score 1 (emms-score-current-selected-track-filename)) (error "No track currently playing"))) (defun emms-score-down-playing () (interactive) (if emms-player-playing-p (emms-score-change-score -1 (emms-score-current-selected-track-filename)) (error "No track currently playing"))) (defun emms-score-up-file-on-line () (interactive) (emms-score-change-score 1 (emms-score-track-at-filename))) (defun emms-score-down-file-on-line () (interactive) (emms-score-change-score -1 (emms-score-track-at-filename))) (defun emms-score-less-tolerant () "Only play mp3 with a higher score" (interactive) (setq emms-score-min-score (+ emms-score-min-score 1)) (message "Will play songs with a score >= %d" emms-score-min-score)) (defun emms-score-more-tolerant () "Allow playing of mp3 with a lower score." (interactive) (setq emms-score-min-score (- emms-score-min-score 1)) (message "Will play songs with a score >= %d" emms-score-min-score)) (defun emms-score-set-playing (score) "Set score for current playing track." (interactive "nSet score for playing track: ") (let ((filename (emms-score-current-selected-track-filename))) (if emms-player-playing-p (emms-score-change-score (- score (emms-score-get-score filename)) filename) (error "No track currently playing")))) (defun emms-score-set-file-on-line (score) "Set score for track at point in emms-playlist buffer." (interactive "nSet score for track at point: ") (let ((filename (emms-score-track-at-filename))) (if emms-player-playing-p (emms-score-change-score (- score (emms-score-get-score filename)) filename)))) (defun emms-score-set-tolerance (tolerance) "Allow playing tracks with a score >= tolerance." (interactive "nSet tolerance: ") (setq emms-score-min-score tolerance) (message "Will play songs with a score >= %d" emms-score-min-score)) (defun emms-score-show-playing () "Show score for current playing track in minibuf." (interactive) (message "track/tolerance score: %d/%d" (emms-score-get-score (emms-score-current-selected-track-filename)) emms-score-min-score)) (defun emms-score-show-file-on-line () "Show score for track at point in emms-playlist buffer." (interactive) (message "track/tolerance score: %d/%d" (emms-score-get-score (emms-score-track-at-filename)) emms-score-min-score)) ;;; Internal Functions (defun emms-score-current-selected-track-filename () "Return filename of current selected track." (emms-track-get (emms-playlist-current-selected-track) 'name)) (defun emms-score-track-at-filename () "Return file of track at point in emms-playlist buffer." (emms-track-get (emms-playlist-track-at) 'name)) (defun emms-score-ok-track-function (track) "Decide if to skip or play TRACK." (emms-score-check-score (emms-track-get track 'name))) (defun emms-score-save-hash () "Save score hash in `emms-score-file'." (interactive) (unless (file-directory-p (file-name-directory emms-score-file)) (make-directory (file-name-directory emms-score-file))) (with-temp-file emms-score-file (let ((standard-output (current-buffer))) (insert "(") (maphash (lambda (key value) (prin1 (cons key value))) emms-score-hash) (insert ")")))) (defun emms-score-load-hash () "Load score hash from `emms-score-file'." (interactive) (if (file-exists-p emms-score-file) (let ((score-string (with-temp-buffer (emms-insert-file-contents emms-score-file) (buffer-string)))) (if (> (length score-string) 0) (mapc (lambda (elt) (puthash (car elt) (cdr elt) emms-score-hash)) (read score-string))) ;; when file not exists, make empty but valid score file (emms-score-save-hash)))) (defun emms-score-get-plist (filename) (gethash filename emms-score-hash)) (defun emms-score-change-score (score filename) (let ((sp (emms-score-get-plist filename) ) (sc (emms-score-get-score filename))) (puthash filename (plist-put sp emms-score-current-mood (+ sc score)) emms-score-hash) (message "New score is %s" (+ score sc)))) (defun emms-score-create-entry (filename) (puthash filename `(,emms-score-current-mood ,emms-score-default-score) emms-score-hash)) (defun emms-score-get-score (filename) "Return score of TRACK." (let ((plist (emms-score-get-plist filename))) (if (member emms-score-current-mood plist) (plist-get plist emms-score-current-mood) (emms-score-create-entry filename) (emms-score-get-score filename)))) (defun emms-score-check-score (filename) (>= (emms-score-get-score filename) emms-score-min-score)) (provide 'emms-score) ;;; emms-scores.el ends here �����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������emms-6.00/emms-setup.el�����������������������������������������������������������������������������0000664�0001750�0001750�00000011240�13746063641�013227� 0����������������������������������������������������������������������������������������������������ustar �yrk�����������������������������yrk��������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������;;; emms-setup.el --- Setup script for EMMS ;; Copyright (C) 2005-2020 Free Software Foundation, Inc. ;; Author: Yoni Rabkin <yrk@gnu.org> ;; Keywords: emms setup multimedia ;; 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, 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; see the file COPYING. If not, write to the ;; Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, ;; Boston, MA 02110-1301, USA. ;;; Commentary: ;; This file provides the `emms-setup' feature. With `emms-setup' we ;; can setup Emms with different features enabled. The use of this ;; feature is documented in the Emms manual which is distributed with ;; Emms. ;; ;; The use this feature we can invoke (for example): ;; ;; (require 'emms-setup) ;; (emms-all) ;; ;; The first command loads the feature into Emacs and the second ;; chooses the `emms-all' level. ;;; Code: (require 'emms) (defgroup emms-setup nil "*The Emacs Multimedia System setup utility." :prefix "emms-setup" :group 'multimedia) (defcustom emms-setup-default-player-list '(emms-player-mpg321 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." :group 'emms-setup :type 'list) ;;;###autoload (defun emms-minimalistic () "An Emms setup script. Invisible playlists and all the basics for playing media." (require 'emms-source-file) (require 'emms-source-playlist) (require 'emms-player-simple) (require 'emms-player-mplayer) (require 'emms-player-mpv) (require 'emms-player-vlc)) ;;;###autoload (defun emms-all () "An Emms setup script. Everything included in the `emms-minimalistic' setup and adds all the stable features which come with the Emms distribution." ;; include (emms-minimalistic) ;; define (eval-and-compile (require 'emms-playlist-mode) (require 'emms-info) (require 'emms-info-mp3info) (require 'emms-info-ogginfo) (require 'emms-info-opusinfo) (require 'emms-info-metaflac) (require 'emms-info-tinytag) (require 'emms-info-exiftool) (require 'emms-cache) (require 'emms-mode-line) (require 'emms-mark) (require 'emms-tag-editor) (require 'emms-show-all) (require 'emms-streams) (require 'emms-lyrics) (require 'emms-playing-time) (require 'emms-player-mpd) (require 'emms-player-xine) (require 'emms-playlist-sort) (require 'emms-browser) (require 'emms-mode-line-icon) (require 'emms-cue) (require 'emms-bookmarks) (require 'emms-last-played) (require 'emms-metaplaylist-mode) (require 'emms-stream-info) (require 'emms-score) (require 'emms-history) (require 'emms-i18n) (require 'emms-volume) (require 'emms-playlist-limit) (require 'emms-librefm-scrobbler) (require 'emms-librefm-stream)) ;; setup (setq emms-playlist-default-major-mode 'emms-playlist-mode) (add-to-list 'emms-track-initialize-functions 'emms-info-initialize-track) (when (executable-find emms-info-mp3info-program-name) (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)) (emms-mode-line 1) (emms-mode-line-blank) (emms-lyrics 1) (emms-playing-time 1) (add-to-list 'emms-info-functions 'emms-info-cueinfo) (add-hook 'emms-player-started-hook 'emms-last-played-update-current) (emms-score 1)) ;;;###autoload (defun emms-default-players () "Set `emms-player-list' to `emms-setup-default-player-list'." (setq emms-player-list emms-setup-default-player-list)) ;; These are kept around in order not to break anyone's existing ;; setup. ;;;###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) ;;; emms-setup.el ends here ����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������emms-6.00/emms-show-all.el��������������������������������������������������������������������������0000664�0001750�0001750�00000007600�13746063641�013622� 0����������������������������������������������������������������������������������������������������ustar �yrk�����������������������������yrk��������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������;;; emms-show-all.el --- Detailed track information for Emms. ;; Copyright (C) 2016 Free Software Foundation, Inc. ;; Author: Yoni Rabkin <yrk@gnu.org> ;; 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, 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: ;;; ;;; Shows all of the available information Emms can provide on the ;;; currently playing track. Based on an idea suggested on the ;;; emms-help mailing list by Ivan Truskov. ;;; Code: (require 'emms) (require 'emms-tag-editor) (defvar emms-show-all-buffer-name "Emms Track Information" "Name of buffer used by `emms-show-all'.") (defvar emms-show-all-kill-buffer-on-quit-p nil "If t, kill the show-all buffer when quitting.") (defvar emms-show-all-track-alist nil "Declare so as to silence the compiler.") (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) (define-key map (kbd "E") 'emms-show-all-edit-track) map) "Keymap for `emms-show-all-mode'.") (define-derived-mode emms-show-all-mode text-mode "Emms-Show-All" "Major mode for `emms-show-all' \\{emms-show-all-mode-map}") (defun emms-show-all-edit-track () "Edit the track being shown." (interactive) (let ((track emms-show-all-track-alist)) (emms-show-all-mode-bury-buffer) (emms-tag-editor-edit-track track))) (defun emms-show-all-mode-bury-buffer () "Bury, and optionally kill the show buffer." (interactive) (quit-restore-window (selected-window) (when emms-show-all-kill-buffer-on-quit-p 'kill))) (defun emms-show-all-setup-buffer () "Prepare the display buffer." (let ((buffer (get-buffer-create emms-show-all-buffer-name))) (with-current-buffer buffer (when (not (local-variable-p 'emms-show-all-track-alist)) (make-local-variable 'emms-show-all-track-alist)) (setq buffer-read-only t) (when (not (equal major-mode 'emms-show-all-mode)) (emms-show-all-mode)) (let ((inhibit-read-only t)) (erase-buffer))) buffer)) (defun emms-show-all-format (track) "Format information for TRACK." (let ((s "")) (dolist (e (mapcar #'(lambda (tag) (cons (format "%s" (car tag)) (or (emms-track-get track (car tag)) ""))) emms-tag-editor-tags)) (setq s (concat s (format "%-17s: %s\n" (car e) (cdr e))))) s)) (defun emms-show-all-insert (track) "Insert information for TRACK in current buffer." (let ((type (emms-track-type track))) (cond ((eq 'file type) (insert (emms-show-all-format track))) ((eq 'url type) (insert (emms-format-url-track-name (emms-track-name track)))) (t (concat (symbol-name type) ": " (emms-track-name track)))))) (defun emms-show-all-track (track) "Display information for TRACK." (let ((buffer (emms-show-all-setup-buffer))) (with-current-buffer buffer (let ((inhibit-read-only t)) (setq emms-show-all-track-alist track) (emms-show-all-insert track)) (pop-to-buffer (current-buffer))))) (defun emms-show-all () "Describe the current EMMS track in detail." (interactive) (if emms-player-playing-p (emms-show-all-track (emms-playlist-current-selected-track)) (message "nothing playing right now"))) (provide 'emms-show-all) ;;; emms-playlist-mode.el ends here ��������������������������������������������������������������������������������������������������������������������������������emms-6.00/emms-source-file.el�����������������������������������������������������������������������0000664�0001750�0001750�00000027122�13746063641�014312� 0����������������������������������������������������������������������������������������������������ustar �yrk�����������������������������yrk��������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������;;; emms-source-file.el --- EMMS sources from the filesystem. ;; Copyright (C) 2003, 2004, 2005, 2006, 2007, 2008, ;; 2009 Free Software Foundation, Inc. ;; Author: Jorgen Schäfer <forcer@forcix.cx> ;; Keywords: emms, mp3, mpeg, multimedia ;; 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, 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; see the file COPYING. If not, write to the ;; Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, ;; Boston, MA 02110-1301, USA. ;;; Commentary: ;; This file contains a track source for EMMS that is based on the ;; file system. You can retrieve single files or whole directories. ;; Also, this file offers the commands to play from these sources. ;;; Code: ;; Version control (defvar emms-source-file-version "0.2 $Revision: 1.30 $" "emms-source-file.el version string") ;; $Id: emms-source-file.el,v 1.30 2005/08/11 06:16:15 yonirabkin Exp $ ;;; User Customization (require 'emms) (require 'dired) (require 'locate) (eval-when-compile (condition-case nil (require 'locate) (error nil))) (require 'dired) (defgroup emms-source-file nil "*Sources for EMMS that use the file system." :prefix "emms-source-file-" :group 'emms-source) (defcustom emms-source-file-default-directory nil "*The default directory to look for media files." :type '(choice (const :tag "None" nil) file) :group 'emms-source-file) (defcustom emms-source-file-directory-tree-function 'emms-source-file-directory-tree-internal "*A function to call that searches in a given directory all files that match a given regex. DIR and REGEX are the only arguments passed to this function. You have two build-in options: `emms-source-file-directory-tree-internal' will work always, but might be slow. `emms-source-file-directory-tree-find' will work only if you have GNU find, but it's faster." :type 'function :options '(emms-source-file-directory-tree-internal emms-source-file-directory-tree-find) :group 'emms-source-file) (defcustom emms-source-file-exclude-regexp (concat "\\`\\(#.*#\\|.*,v\\|.*~\\|\\.\\.?\\|\\.#.*\\|,.*\\)\\'\\|" "/\\(CVS\\|RCS\\|\\.arch-ids\\|{arch}\\|,.*\\|\\.svn\\|" "_darcs\\)\\(/\\|\\'\\)") "A regexp matching files to be ignored when adding directories. You should set case-fold-search to nil before using this regexp in code." :type 'regexp :group 'emms-source-file) (defcustom emms-source-file-gnu-find "find" "*The program name for GNU find." :type 'string :group 'emms-source-file) (defcustom emms-source-file-directory-hint-p t "*When non-nil, guess the directory based on a track at point." :type 'boolean :group 'emms-source-file) ;; The `read-directory-name' function is not available in Emacs 21. (defalias 'emms-read-directory-name (if (fboundp 'read-directory-name) #'read-directory-name #'read-file-name)) (defun emms-source-file-directory-hint () (if (and emms-source-file-directory-hint-p emms-playlist-buffer-p (emms-playlist-track-at)) (let ((name (emms-track-get (emms-playlist-track-at) 'name)) (type (emms-track-get (emms-playlist-track-at) 'type))) (when (eq type 'file) (file-name-directory name))) emms-source-file-default-directory)) ;;; Sources ;;;###autoload (autoload 'emms-play-file "emms-source-file" nil t) ;;;###autoload (autoload 'emms-add-file "emms-source-file" nil t) (define-emms-source file (file) "An EMMS source for a single file - either FILE, or queried from the user." (interactive (list (read-file-name "Play file: " (emms-source-file-directory-hint) emms-source-file-default-directory t))) (if (file-directory-p file) (emms-source-directory file) (emms-playlist-insert-track (emms-track 'file (expand-file-name file))))) ;;;###autoload (autoload 'emms-play-directory "emms-source-file" nil t) ;;;###autoload (autoload 'emms-add-directory "emms-source-file" nil t) (define-emms-source directory (dir) "An EMMS source for a whole directory tree - either DIR, or queried from the user." (interactive (list (emms-read-directory-name "Play directory: " (emms-source-file-directory-hint) emms-source-file-default-directory t))) (mapc (lambda (file) (unless (or (let ((case-fold-search nil)) (string-match emms-source-file-exclude-regexp file)) (file-directory-p file)) (emms-playlist-insert-track (emms-track 'file (expand-file-name file))))) (directory-files dir t (emms-source-file-regex)))) ;;;###autoload (autoload 'emms-play-directory-tree "emms-source-file" nil t) ;;;###autoload (autoload 'emms-add-directory-tree "emms-source-file" nil t) (define-emms-source directory-tree (dir) "An EMMS source for multiple directory trees - either DIR, or the value of `emms-source-file-default-directory'." (interactive (list (emms-read-directory-name "Play directory tree: " (emms-source-file-directory-hint) emms-source-file-default-directory t))) (let ((files (emms-source-file-directory-tree (expand-file-name dir) (emms-source-file-regex))) (case-fold-search nil)) (emms-playlist-ensure-playlist-buffer) (mapc (lambda (file) (unless (string-match emms-source-file-exclude-regexp file) (funcall emms-playlist-insert-track-function (emms-track 'file file)))) files))) ;;;###autoload (autoload 'emms-play-find "emms-source-file" nil t) ;;;###autoload (autoload 'emms-add-find "emms-source-file" nil t) (define-emms-source find (dir regex) "An EMMS source that will find files in DIR or `emms-source-file-default-directory' that match REGEX." (interactive (list (emms-read-directory-name "Find in directory: " emms-source-file-default-directory emms-source-file-default-directory t) (read-from-minibuffer "Find files matching: "))) (mapc (lambda (file) (unless (let ((case-fold-search nil)) (string-match emms-source-file-exclude-regexp file)) (emms-playlist-insert-track (emms-track 'file file)))) (emms-source-file-directory-tree (expand-file-name dir) regex))) ;;;###autoload (autoload 'emms-play-dired "emms-source-file" nil t) ;;;###autoload (autoload 'emms-add-dired "emms-source-file" nil t) (define-emms-source dired () "Return all marked files of a dired buffer" (interactive) (mapc (lambda (file) (if (file-directory-p file) (emms-source-directory-tree file) (emms-source-file file))) (with-current-buffer emms-source-old-buffer (dired-get-marked-files)))) ;;; Helper functions ;;;###autoload (defun emms-source-file-directory-tree (dir regex) "Return a list of all files under DIR that match REGEX. This function uses `emms-source-file-directory-tree-function'." (message "Building playlist...") (let ((pl (sort (funcall emms-source-file-directory-tree-function dir regex) 'string<))) (message "Building playlist...done") pl)) (defun emms-source-file-directory-tree-internal (dir regex) "Return a list of all files under DIR that match REGEX. This function uses only emacs functions, so it might be a bit slow." (let ((files '()) (dirs (list dir))) (while dirs (cond ((file-directory-p (car dirs)) (if (or (string-match "/\\.\\.?$" (car dirs)) (let ((symlink (file-symlink-p (car dirs)))) (and symlink (string-equal dir (substring symlink 0 (string-width dir)))))) (setq dirs (cdr dirs)) (setq dirs (condition-case nil (append (cdr dirs) (directory-files (car dirs) t nil t)) (error (cdr dirs)))))) ((string-match regex (car dirs)) (setq files (cons (car dirs) files) dirs (cdr dirs))) (t (setq dirs (cdr dirs))))) files)) (defun emms-source-file-directory-tree-find (dir regex) "Return a list of all files under DIR that match REGEX. This function uses the external find utility. The name for GNU find may be supplied using `emms-source-file-gnu-find'." (with-temp-buffer (call-process emms-source-file-gnu-find nil t nil "-L" ; follow symlinks (expand-file-name dir) "-type" "f" "-iregex" (concat ".*\\(" regex "\\).*")) (delete "" (split-string (buffer-substring (point-min) (point-max)) "\n")))) (defmacro emms-with-excluded-directories (directory-list &rest body) "Run BODY while excluding DIRECTORY-LIST." `(let ((emms-source-file-exclude-regexp (concat (or ,emms-source-file-exclude-regexp "") "\\|\\(" (or (regexp-opt ,directory-list) "") "\\)"))) ,@body)) ;;;###autoload (defun emms-source-file-regex () "Return a regexp that matches everything any player (that supports files) can play." (mapconcat (lambda (player) (or (emms-player-get player 'regex) "")) emms-player-list "\\|")) ;; emms-locate should be part of a once to be emms-dired, with maybe ;; file rename after tag functions and so on, but till then i park it ;; here... :) ;;;###autoload (defun emms-locate (regexp) "Search for REGEXP and display the results in a locate buffer" (interactive "sRegexp to search for: ") (require 'locate) (save-window-excursion (set-buffer (get-buffer-create "*EMMS Find*")) (locate-mode) (erase-buffer) (mapc (lambda (elt) (insert (cdr (assoc 'name elt)) "\n")) (emms-source-find emms-source-file-default-directory regexp)) (locate-do-setup regexp)) (and (not (string-equal (buffer-name) "*EMMS Find*")) (switch-to-buffer-other-window "*EMMS Find*")) (run-hooks 'dired-mode-hook) (dired-next-line 2)) ;; Strictly speaking, this does not belong in this file (URLs are not ;; real files), but it's close enough :-) ;;;###autoload (autoload 'emms-play-url "emms-source-file" nil t) ;;;###autoload (autoload 'emms-add-url "emms-source-file" nil t) (define-emms-source url (url) "An EMMS source for an URL - for example, for streaming." (interactive "sPlay URL: ") (emms-playlist-insert-track (emms-track 'url url))) ;;;###autoload (autoload 'emms-play-streamlist "emms-source-file" nil t) ;;;###autoload (autoload 'emms-add-streamlist "emms-source-file" nil t) (define-emms-source streamlist (streamlist) "An EMMS source for streaming playlists (usually URLs ending in .pls)." (interactive "sPlay streamlist URL: ") (emms-playlist-insert-track (emms-track 'streamlist streamlist))) (provide 'emms-source-file) ;;; emms-source-file.el ends here ����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������emms-6.00/emms-source-playlist.el�������������������������������������������������������������������0000664�0001750�0001750�00000046321�13746063641�015236� 0����������������������������������������������������������������������������������������������������ustar �yrk�����������������������������yrk��������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������;;; emms-source-playlist.el --- EMMS sources from playlist files ;; Copyright (C) 2003, 2004, 2005, 2006, 2007, 2008, ;; 2009 Free Software Foundation, Inc. ;; Author: Jorgen Schäfer <forcer@forcix.cx> ;; Keywords: emms, mp3, mpeg, multimedia ;; 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, 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; see the file COPYING. If not, write to the ;; Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, ;; Boston, MA 02110-1301, USA. ;;; Commentary: ;; This file contains track sources for EMMS which read playlist ;; files. EMMS' own playlist files are supported as well as .m3u and ;; .pls files. ;;; Code: ;; Version control (defvar emms-source-playlist-version "0.5 $Revision: 1.30 $" "emms-source-playlist.el version string") ;; $Id: emms-source-file.el,v 1.30 2005/08/11 06:16:15 yonirabkin Exp $ (require 'emms) (require 'emms-source-file) (defcustom emms-source-playlist-formats '(native pls m3u) "*A list of playlist formats. Each entry must have at least three corresponding functions. First, a function named `emms-source-playlist-FORMAT-p' which returns non-nil if the current buffer is of the type FORMAT. It is called with no arguments. Second, a function named `emms-source-playlist-parse-FORMAT' which parses the current buffer into tracks. It is called with no arguments. Third, a function named `emms-source-playlist-unparse-FORMAT' which creates an output file in the type FORMAT that contains the tracks of a playlist buffer. It is called with two arguments: The playlist buffer and the file buffer. It is also recommended to have a function named `emms-source-playlist-FORMAT-files' which returns a list of the files contained in the playlist." :type '(repeat (symbol :tag "Format")) :group 'emms) (defcustom emms-source-playlist-default-format nil "*The default format to use for saving playlists. If this is nil, you will be prompted for a format to use." :type '(choice (const :tag "Prompt each time" nil) (const :tag "Native" native) (const :tag "m3u" m3u) (const :tag "pls" pls) (symbol :tag "Other")) :group 'emms) (defcustom emms-source-playlist-ask-before-overwrite t "*Ask before saving over an existing playlist. If this is nil, existing playlists will be quietly overwritten." :type 'boolean :group 'emms) (defvar emms-source-playlist-native-header-line ";;; This is an EMMS playlist file" "Line which identifies a native emms playlist.") ;;; General playlist (defsubst emms-source-playlist-p-sym (format) (intern (concat "emms-source-playlist-" (symbol-name format) "-p"))) (defsubst emms-source-playlist-parse-sym (format) (intern (concat "emms-source-playlist-parse-" (symbol-name format)))) (defsubst emms-source-playlist-unparse-sym (format) (intern (concat "emms-source-playlist-unparse-" (symbol-name format)))) (defsubst emms-source-playlist-files-sym (format) (intern (concat "emms-source-playlist-" (symbol-name format) "-files"))) (defun emms-source-playlist-p (format &optional parse-files) (let ((sym (emms-source-playlist-p-sym format))) (when (and (functionp sym) (or (not parse-files) (functionp (emms-source-playlist-files-sym format)))) (funcall sym)))) (defun emms-source-playlist-parse (format file) (funcall (emms-source-playlist-parse-sym format) file)) (defun emms-source-playlist-unparse (format playlist-buf file-buf) (funcall (emms-source-playlist-unparse-sym format) playlist-buf file-buf)) (defun emms-source-playlist-files (format) (let ((sym (emms-source-playlist-files-sym format))) (if (functionp sym) (funcall sym) (error "The `%s' format cannot parse files from a playlist" format)))) (defvar emms-source-playlist-format-history nil "List of recently-entered formats; used by `emms-playlist-save'.") (defun emms-source-playlist-read-format () "Read a playlist format from the user. If `emms-source-playlist-default-format' is non-nil, use it instead of prompting the user." (or emms-source-playlist-default-format (let ((format (emms-completing-read (concat "Playlist format: (default: " (if emms-source-playlist-format-history (car emms-source-playlist-format-history) "native") ") ") (mapcar #'symbol-name emms-source-playlist-formats) nil nil nil 'emms-source-playlist-format-history (if emms-source-playlist-format-history (car emms-source-playlist-format-history) "native")))) ;; Sometimes the completion function can put partial results ;; onto the history, so pop the last one off and include the ;; completed version instead. (setq emms-source-playlist-format-history (cons format (cdr emms-source-playlist-format-history))) (intern format)))) (defun emms-playlist-save (format file) "Store the current playlist to FILE as the type FORMAT. The default format is specified by `emms-source-playlist-default-format'." (interactive (list (emms-source-playlist-read-format) (read-file-name "Store as: " emms-source-file-default-directory emms-source-file-default-directory nil))) (if (or (eq emms-playlist-buffer (current-buffer)) (and (not (eq emms-playlist-buffer (current-buffer))) (y-or-n-p (format "Current playlist buffer (%s) is not the one you are visiting (%s). Save anyway?" emms-playlist-buffer (current-buffer))))) (with-temp-buffer (emms-source-playlist-unparse format (with-current-emms-playlist (current-buffer)) (current-buffer)) (let ((backup-inhibited t)) (write-file file emms-source-playlist-ask-before-overwrite))) (message "aborting save"))) (defun emms-source-playlist-determine-format (&optional parse-files) "Determine the playlist format of the current buffer. If PARSE-FILES is specified, the given format must be able to return a list of the files contained in the playlist." (catch 'return (let ((formats emms-source-playlist-formats)) (while formats (when (emms-source-playlist-p (car formats) parse-files) (throw 'return (car formats))) (setq formats (cdr formats)))))) ;;;###autoload (autoload 'emms-play-playlist "emms-source-playlist" nil t) ;;;###autoload (autoload 'emms-add-playlist "emms-source-playlist" nil t) (define-emms-source playlist (file) "An EMMS source for playlists. See `emms-source-playlist-formats' for a list of supported formats." (interactive (list (read-file-name "Playlist file: " emms-source-file-default-directory emms-source-file-default-directory t))) (mapc #'emms-playlist-insert-track (with-temp-buffer (emms-insert-file-contents file) (goto-char (point-min)) (let ((format (emms-source-playlist-determine-format))) (if format (emms-source-playlist-parse format file) (error "Not a recognized playlist format")))))) ;;; Emms native playlists ;; An Emms native playlist file starts with the contents of ;; `emms-source-playlist-native-header-line' and is followed by ;; tracks in sexp format. (defun emms-source-playlist-native-p () "Return non-nil if the current buffer contains a native EMMS playlist." (save-excursion (goto-char (point-min)) (looking-at (concat "^" emms-source-playlist-native-header-line)))) (defun emms-source-playlist-parse-native (file) "Parse the native EMMS playlist in the current buffer." (save-excursion (goto-char (point-min)) (read (current-buffer)))) (defun emms-source-playlist-unparse-native (in out) "Unparse a native playlist from IN to OUT. IN should be a buffer with a EMMS playlist in it. OUT should be the buffer where tracks are stored in the native EMMS format." (with-current-buffer in ;; Don't modify the position (save-excursion ;; in the IN buffer (with-current-buffer out (insert emms-source-playlist-native-header-line " Play it with M-x emms-play-playlist\n") (insert "(")) (let ((firstp t)) (goto-char (point-min)) (emms-walk-tracks (let ((track (emms-playlist-track-at (point)))) (with-current-buffer out (if (not firstp) (insert "\n ") (setq firstp nil)) (prin1 track (current-buffer)))))) (with-current-buffer out (insert ")\n"))))) ;;;###autoload (autoload 'emms-play-native-playlist "emms-source-playlist" nil t) ;;;###autoload (autoload 'emms-add-native-playlist "emms-source-playlist" nil t) (define-emms-source native-playlist (file) "An EMMS source for a native EMMS playlist file." (interactive (list (read-file-name "Playlist file: " emms-source-file-default-directory emms-source-file-default-directory t))) (mapc #'emms-playlist-insert-track (with-temp-buffer (emms-insert-file-contents file) (goto-char (point-min)) (when (not (emms-source-playlist-native-p)) (error "Not a native EMMS playlist file.")) (emms-source-playlist-parse-native file)))) ;;; m3u files ;; Format: ;; Either a list of filename-per-line, ignore lines beginning with # ;; or: ;; #EXTM3U ;; #EXTINF:<length in seconds>,<name> ;; <filename> ; emms-source-playlist-m3u-p ; emms-source-playlist-parse-m3u ; emms-source-playlist-m3u-files ; emms-source-playlist-unparse-m3u (defun emms-source-playlist-m3u-p () "Return non-nil if the current buffer contains an m3u playlist. We currently have no metric for determining whether a buffer is an .m3u playlist based on its contents alone, so we assume that the more restrictive playlist formats have already been detected and simply return non-nil always." t) (defun emms-source-playlist-parse-m3u (playlist-file) "Parse the m3u playlist in the current buffer. Files will be relative to the directory of PLAYLIST-FILE, unless they have absolute paths." (let ((dir (file-name-directory playlist-file))) (mapcar (lambda (file) (if (string-match "\\`\\(http[s]?\\|mms\\)://" file) (emms-track 'url file) (emms-track 'file (expand-file-name file dir)))) (emms-source-playlist-m3u-files)))) (defun emms-source-playlist-m3u-files () "Extract a list of filenames from the given m3u playlist. Empty lines and lines starting with '#' are ignored." (let ((files nil)) (save-excursion (goto-char (point-min)) (while (re-search-forward "^[^# \n].*$" nil t) (setq files (cons (match-string 0) files)))) (nreverse files))) (defun emms-source-playlist-unparse-m3u (in out) "Unparse an m3u playlist from IN to OUT. IN should be a buffer containing an m3u playlist. OUT should be the buffer where tracks are stored in m3u format." (with-current-buffer in ;; Don't modify the position (save-excursion ;; in the IN buffer (goto-char (point-min)) (emms-walk-tracks (let ((track (emms-playlist-track-at (point)))) (with-current-buffer out (insert (emms-track-name track) ?\n))))))) ;;;###autoload (autoload 'emms-play-m3u-playlist "emms-source-playlist" nil t) ;;;###autoload (autoload 'emms-add-m3u-playlist "emms-source-playlist" nil t) (define-emms-source m3u-playlist (file) "An EMMS source for an m3u playlist file." (interactive (list (read-file-name "Playlist file: " emms-source-file-default-directory emms-source-file-default-directory t))) (mapc #'emms-playlist-insert-track (with-temp-buffer (emms-insert-file-contents file) (goto-char (point-min)) (when (not (emms-source-playlist-m3u-p)) (error "Not an m3u playlist file.")) (emms-source-playlist-parse-m3u file)))) ;;; pls files ;; Format: ;; A list of one filename per line. ;; [playlist] ;; NumberOfEntries=<num_entries> ;; File<position>=<filename> ; emms-source-playlist-pls-p ; emms-source-playlist-parse-pls ; emms-source-playlist-pls-files ; emms-source-playlist-unparse-pls (defun emms-source-playlist-pls-p () "Return non-nil if the current buffer contains a pls playlist." (save-excursion (goto-char (point-min)) (if (re-search-forward "^File[0-9]*=.+$" nil t) t nil))) (defun emms-source-playlist-parse-pls (playlist-file) "Parse the pls playlist in the current buffer. Files will be relative to the directory of PLAYLIST-FILE, unless they have absolute paths." (let ((dir (file-name-directory playlist-file))) (mapcar (lambda (file) (if (string-match "\\`\\(http[s]?\\|mms\\)://" file) (emms-track 'url file) (if (string-match "\\`file://" file) ;; handle file:// uris (let ((file (url-unhex-string (substring file 7)))) (emms-track 'file file)) (emms-track 'file (expand-file-name file dir))))) (emms-source-playlist-pls-files)))) (defun emms-source-playlist-pls-files () "Extract a list of filenames from the given pls playlist. Empty lines and lines starting with '#' are ignored." (let ((files nil)) (save-excursion (goto-char (point-min)) (while (re-search-forward "^File[0-9]*=\\(.+\\)$" nil t) (setq files (cons (match-string 1) files)))) (nreverse files))) (defun emms-source-playlist-unparse-pls (in out) "Unparse a pls playlist from IN to OUT. IN should be a buffer conatining a pls playlist. OUT should be the buffer where tracks are stored in pls format." (with-current-buffer in ;; Don't modify the position (save-excursion ;; in the IN buffer (let ((pos 0) beg) (with-current-buffer out (insert "[playlist]\n") (setq beg (point))) (goto-char (point-min)) (emms-walk-tracks (let ((track (emms-playlist-track-at (point)))) (setq pos (1+ pos)) (with-current-buffer out (insert "File" (number-to-string pos) "=" (emms-track-name track) ?\n)))) (with-current-buffer out (goto-char beg) (insert "NumberOfEntries=" (number-to-string pos) ?\n)))))) ;;;###autoload (autoload 'emms-play-pls-playlist "emms-source-playlist" nil t) ;;;###autoload (autoload 'emms-add-pls-playlist "emms-source-playlist" nil t) (define-emms-source pls-playlist (file) "An EMMS source for a pls playlist file." (interactive (list (read-file-name "Playlist file: " emms-source-file-default-directory emms-source-file-default-directory t))) (mapc #'emms-playlist-insert-track (with-temp-buffer (emms-insert-file-contents file) (goto-char (point-min)) (when (not (emms-source-playlist-pls-p)) (error "Not a pls playlist file.")) (emms-source-playlist-parse-pls file)))) ;;; extm3u files ;; Format: ;; #EXTM3U ;; #EXTINF:<length in seconds>,<name> ;; <filename> ; emms-source-playlist-extm3u-p ; emms-source-playlist-parse-extm3u ; emms-source-playlist-unparse-extm3u ;; (erase-buffer) ;; (insert "#EXTM3U\n") ;; (mapc (lambda (track) ;; (let ((time (or (emms-track-get track 'info-mtime) "")) ;; (artist (emms-track-get track 'info-artist)) ;; (title (emms-track-get track 'info-title)) ;; (name (emms-track-get track 'name))) ;; (insert (format "#EXTINF: %s,%s - %s\n%s\n" ;; time artist title name)))) ;; tracklist) ;; (save-buffer) ;; (kill-buffer (current-buffer))))) ;; Not implemented yet ;;; Adding playlists as files ;;;###autoload (autoload 'emms-play-playlist-file "emms-source-playlist" nil t) ;;;###autoload (autoload 'emms-add-playlist-file "emms-source-playlist" nil t) (define-emms-source playlist-file (file) "An EMMS source for playlist files. This adds the given file to the current EMMS playlist buffer, without adding its contents. See `emms-source-playlist-formats' for a list of supported formats." (interactive (list (read-file-name "Playlist file: " emms-source-file-default-directory emms-source-file-default-directory t))) (emms-playlist-insert-track (emms-track 'playlist (expand-file-name file)))) ;;;###autoload (autoload 'emms-play-playlist-directory ;;;###autoload "emms-source-playlist" nil t) ;;;###autoload (autoload 'emms-add-playlist-directory ;;;###autoload "emms-source-playlist" nil t) (define-emms-source playlist-directory (dir) "An EMMS source for a whole directory tree of playlist files. If DIR is not specified, it is queried from the user." (interactive (list (emms-read-directory-name "Play directory: " emms-source-file-default-directory emms-source-file-default-directory t))) (mapc (lambda (file) (unless (or (let ((case-fold-search nil)) (string-match emms-source-file-exclude-regexp file)) (file-directory-p file)) (emms-playlist-insert-track (emms-track 'playlist (expand-file-name file))))) (directory-files dir t "^[^.]"))) ;;;###autoload (autoload 'emms-play-playlist-directory-tree ;;;###autoload "emms-source-playlist" nil t) ;;;###autoload (autoload 'emms-add-playlist-directory-tree ;;;###autoload "emms-source-file" nil t) (define-emms-source playlist-directory-tree (dir) "An EMMS source for multiple directory trees of playlist files. If DIR is not specified, it is queried from the user." (interactive (list (emms-read-directory-name "Play directory tree: " emms-source-file-default-directory emms-source-file-default-directory t))) (mapc (lambda (file) (unless (let ((case-fold-search nil)) (string-match emms-source-file-exclude-regexp file)) (emms-playlist-insert-track (emms-track 'playlist file)))) (emms-source-file-directory-tree (expand-file-name dir) "^[^.]"))) (provide 'emms-source-playlist) ;;; emms-source-playlist.el ends here ���������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������emms-6.00/emms-stream-info.el�����������������������������������������������������������������������0000664�0001750�0001750�00000001753�13746063641�014323� 0����������������������������������������������������������������������������������������������������ustar �yrk�����������������������������yrk��������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������;;; emms-stream-info.el --- Info from streaming audio ;; Copyright (C) 2004, 2005, 2006, 2007, 2008, ;; 2009, 2019 Free Software Foundation, Inc. ;; Author: Yoni Rabkin <yrk@gnu.org> ;; 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. ;;; Code: ;; to be implemented! (provide 'emms-stream-info) ;;; emms-stream-info.el ends here ���������������������emms-6.00/emms-streams.el���������������������������������������������������������������������������0000664�0001750�0001750�00000017327�13746063641�013561� 0����������������������������������������������������������������������������������������������������ustar �yrk�����������������������������yrk��������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������;; emms-streams.el -- A collection of online streaming audio ;; Copyright (C) 2019 Free Software Foundation, Inc. ;; Authors: Yoni Rabkin <yrk@gnu.org> ;; 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: ;; 2019-11-05 - This is a complete re-write of the emms-streams.el, ;; using a different approach. ;; This includes the built-in list of streams which come with Emms by ;; default. Emms has no affiliation of any kind with the streaming ;; audio stations listed below, nor is this an endorsement of these ;; stations. Instead, this is a collection of stations submitted to ;; the project over the years by people who enjoy Emms. We hope you ;; will enjoy them too. ;;; Code: (require 'emms) (require 'emms-source-playlist) (require 'emms-playlist-mode) ;;; ------------------------------------------------------------------ ;;; definitions ;;; ------------------------------------------------------------------ (defvar emms-streams-buffer-name "Emms Streams" "Name for creating a streams buffer.") (defvar emms-streams-built-in-disclaimer ";; This includes the built-in list of streams which come with Emms by ;; default. Emms has no affiliation of any kind with the streaming ;; audio stations listed below, nor is this an endorsement of these ;; stations. Instead, this is a collection of stations submitted to ;; the project over the years by people who enjoy Emms. We hope you ;; will enjoy them too." "Explaining the relationship between Emms and these streams.") (defvar emms-streams-built-in-list '((*track* (type . streamlist) (name . "http://www.somafm.com/beatblender.pls") (metadata "SomaFM: Beatblender" "http://www.somafm.com/beatblender.pls" 1 streamlist)) (*track* (type . streamlist) (name . "http://www.somafm.com/secretagent.pls") (metadata "SomaFM: Secret Agent" "http://www.somafm.com/secretagent.pls" 1 streamlist)) (*track* (type . streamlist) (name . "http://www.somafm.com/groovesalad.pls") (metadata "SomaFM: Groove Salad" "http://www.somafm.com/groovesalad.pls" 1 streamlist)) (*track* (type . streamlist) (name . "http://www.somafm.com/dronezone.pls") (metadata "SomaFM: Drone Zone" "http://www.somafm.com/dronezone.pls" 1 streamlist)) (*track* (type . streamlist) (name . "http://www.somafm.com/tagstrance.pls") (metadata "SomaFM: Tag's Trance" "http://www.somafm.com/tagstrance.pls" 1 streamlist)) (*track* (type . streamlist) (name . "http://www.somafm.com/indiepop.pls") (metadata "SomaFM: Indie Pop Rocks" "http://www.somafm.com/indiepop.pls" 1 streamlist)) (*track* (type . streamlist) (name . "http://www.somafm.com/doomed.pls") (metadata "SomaFM: Doomed" "http://www.somafm.com/doomed.pls" 1 streamlist)) (*track* (type . url) (name . "http://listen.radionomy.com:80/-PHILOSOMATIKAPROGRESSIVE-") (metadata "P H I L O S O M A T I K A - Progressive Psytrance" "http://listen.radionomy.com:80/-PHILOSOMATIKAPROGRESSIVE-" 1 url)) (*track* (type . streamlist) (name . "http://www.bassdrive.com/BassDrive.m3u") (metadata "Drum and Bass Radio, BassDrive" "http://www.bassdrive.com/BassDrive.m3u" 1 streamlist)) (*track* (type . streamlist) (name . "http://www.ibiblio.org/wcpe/wcpe.pls") (metadata "WCPE, Classical Music" "http://www.ibiblio.org/wcpe/wcpe.pls" 1 streamlist)) (*track* (type . streamlist) (name . "http://stream.nute.net/kohina/stream.ogg.m3u") (metadata "Kohina - Old school game and demo music" "http://stream.nute.net/kohina/stream.ogg.m3u" 1 streamlist)) (*track* (type . streamlist) (name . "http://privat.is-by.us:8000/necta192.mp3.m3u") (metadata "Nectarine, Demoscene Radio, DE Continuum's relay 192 mp3" "http://privat.is-by.us:8000/necta192.mp3.m3u" 1 streamlist)) (*track* (type . streamlist) (name . "http://nectarine.from-de.com/necta192.m3u") (metadata "Nectarine, Demoscene Radio, DE stream (High Bitrate)" "http://nectarine.from-de.com/necta192.m3u" 1 streamlist)) (*track* (type . streamlist) (name . "http://www.wfmu.org/wfmu.pls") (metadata "WFMU, Freeform radio" "http://www.wfmu.org/wfmu.pls" 1 streamlist)) (*track* (type . streamlist) (name . "http://wfmu.org/wfmu_rock.pls") (metadata "WFMU, Rock'n'Soul Ichiban!" "http://www.wfmu.org/wfmu.pls" 1 streamlist)) (*track* (type . streamlist) (name . "http://wfmu.org/wfmu_drummer.pls") (metadata "WFMU, Give the Drummer Radio" "http://www.wfmu.org/wfmu.pls" 1 streamlist)) (*track* (type . streamlist) (name . "http://wfmu.org/wfmu_sheena.pls") (metadata "WFMU, Sheena's Jungle Room" "http://www.wfmu.org/wfmu.pls" 1 streamlist)) (*track* (type . streamlist) (name . "http://nyc01.egihosting.com:6232/listen.pls") (metadata "WBCR-LP - Berkshire Community Radio" "http://nyc01.egihosting.com:6232/listen.pls" 1 streamlist)) (*track* (type . streamlist) (name . "http://199.244.85.125:8000/wxhq1") (metadata "WXHQ-LP - Newport Radio" "http://199.244.85.125:8000/wxhq1" 1 streamlist)))) (defcustom emms-streams-file (concat (file-name-as-directory emms-directory) "streams.emms") "A file used to store the built-in streams." :group 'emms :type 'file) ;;; ------------------------------------------------------------------ ;;; private functions ;;; ------------------------------------------------------------------ (defun emms-streams-install-file (file) "Install FILE, containing streams." (when (not (file-directory-p (file-name-directory emms-streams-file))) (make-directory (file-name-directory emms-streams-file))) (if (or (not (file-exists-p file)) (and (file-exists-p file) (y-or-n-p (format "overwrite existing %s?" file)))) (progn (message "writing %s" file) (with-temp-buffer (insert emms-source-playlist-native-header-line) (insert (format "\n%s\n\n" emms-streams-built-in-disclaimer)) (insert (concat "(" (mapconcat #'(lambda (e) (format "%S" e)) emms-streams-built-in-list "\n") ")")) (write-region (point-min) (point-max) file)) (message "writing %s... done" file)) (message "aborting"))) ;;; ------------------------------------------------------------------ ;;; interface ;;; ------------------------------------------------------------------ (defun emms-streams-install () (interactive) "Install the built-in streams file." (emms-streams-install-file emms-streams-file)) (defun emms-streams () (interactive) "Create or switch to the built-in streaming audio playlist." (when (and (not (file-exists-p emms-streams-file)) (y-or-n-p "Emms' built-in streams file hasn't been installed yet. Install it now?")) (emms-streams-install)) (let ((buf (get-buffer emms-streams-buffer-name))) (when (not buf) (with-current-buffer (get-buffer-create emms-streams-buffer-name) (setq buf (current-buffer)) (emms-playlist-mode) (setq emms-playlist-buffer-p t) (emms-playlist-set-playlist-buffer (current-buffer)) (emms-add-native-playlist emms-streams-file))) (switch-to-buffer buf))) (provide 'emms-streams) ;;; emms-streams.el ends here ���������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������emms-6.00/emms-tag-editor.el������������������������������������������������������������������������0000664�0001750�0001750�00000076440�13746063641�014143� 0����������������������������������������������������������������������������������������������������ustar �yrk�����������������������������yrk��������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������;;; emms-tag-editor.el --- Edit track tags. ;; Copyright (C) 2006, 2007, 2008, 2009 Free Software Foundation, Inc. ;; ;; Author: Ye Wenbin <wenbinye@163.com> ;; This file is part of EMMS. ;; This program is free software; you can redistribute it and/or modify ;; it under the terms of the GNU General Public License as published by ;; the Free Software Foundation; either version 3, or (at your option) ;; any later version. ;; ;; This program is distributed in the hope that it will be useful, ;; but WITHOUT ANY WARRANTY; without even the implied warranty of ;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ;; GNU General Public License for more details. ;; ;; You should have received a copy of the GNU General Public License ;; along with this program; if not, write to the Free Software ;; Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. ;;; Commentary: ;; Put this file into your load-path and the following into your ~/.emacs: ;; (require 'emms-tag-editor) ;;; Code: (condition-case nil (require 'overlay) (error nil)) (require 'emms) (eval-when-compile (require 'emms-info-metaflac)) (require 'emms-info-mp3info) (require 'emms-playlist-mode) (require 'emms-mark) (require 'format-spec) (defvar emms-tag-editor-tags '((info-artist . "a") (info-composer . "C") (info-performer . "p") (info-title . "t") (info-album . "l") (info-tracknumber . "n") (info-year . "y") (info-genre . "g") (info-date . "d") (info-note . "c")) "An alist to determine the format of various info tags.") (defvar emms-tag-editor-edit-buffer "*EMMS-TAGS*" "Name of the buffer used for editing tags.") (defvar emms-tag-editor-log-buffer "*EMMS-LOG*" "Name of emms-tag-editor's log buffer.") (defun emms-tag-editor-make-format (tags) "Make a format string based on TAGS." (concat "%m\n" (emms-propertize (format "%-16s = " "name") 'read-only t 'rear-nonsticky t 'face 'bold) "%f\n" (mapconcat (lambda (tag) (concat (emms-propertize (format "%-16s = " (symbol-name tag)) 'read-only t 'rear-nonsticky t 'face 'bold) "%" (cdr (assoc tag emms-tag-editor-tags)))) tags "\n") "\n\n")) (defvar emms-tag-editor-formats (let* ((tags (mapcar 'car emms-tag-editor-tags)) (default (emms-tag-editor-make-format (remove 'info-date tags)))) `(("mp3" . ,default) ("ogg" . ,(emms-tag-editor-make-format (remove 'info-year tags))) ("flac" . ,(emms-tag-editor-make-format (remove 'info-year tags))) ("default" . ,default))) "Format to use when inserting the track. The CAR part is the extension of the track name, and the CDR part is the format template. The format specification is like: m -- Track description f -- Track name a -- Track info-artist c -- Track info-composer p -- Track info-performer t -- Track info-title l -- Track info-album n -- Track info-tracknumber D -- Track info-discnumber y -- Track info-year g -- Track info-genre ; -- Track info-note You can add new specifications in `emms-tag-editor-tags', and use `emms-tag-editor-make-format' to create a new format string. The CDR part also can be a function, which accepts one parameter, the track, and returns a string to insert in `emms-tag-editor-edit-buffer'.") (defvar emms-tag-editor-get-format-function 'emms-tag-editor-get-format "Determines which function to call to get the format string, which is used for inserting the track.") (defvar emms-tag-editor-parse-function 'emms-tag-editor-default-parser "Function to parse tags in `emms-tag-editor-edit-buffer'. It should find all modified tags, and return all the tracks. The tracks for which a tag has been modified should set a property 'tag-modified to t. If the track name has been changed, the function should set a new property 'newname instead of setting the 'name directly. See also `emms-tag-editor-default-parser'.") (defvar emms-tag-editor-tagfile-functions '(("mp3" "mid3v2" ((info-artist . "a") (info-title . "t") (info-album . "A") (info-tracknumber . "T") (info-year . "y") (info-genre . "g") (info-note . "c"))) ("ogg" . emms-tag-editor-tag-ogg) ("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, then the list should like: (EXTENSION PROGRAM COMMAND_LINE_OPTIONS) Otherwise, a function that accepts a single parameter, the track, should be given. See also `emms-tag-editor-tag-file' and `emms-tag-editor-tag-ogg'.") (defun emms-tag-editor-tag-flac (track) "Commit changes to an FLAC file according to TRACK." (require 'emms-info-metaflac) (with-temp-buffer (let ((tags '("artist" "composer" "performer" "title" "album" "tracknumber" "discnumber" "date" "genre" "note")) need val) (mapc (lambda (tag) (let ((info-tag (intern (concat "info-" tag)))) (when (> (length (setq val (emms-track-get track info-tag))) 0) (insert (upcase tag) "=" val "\n")))) tags) (when (buffer-string) (apply #'call-process-region (point-min) (point-max) emms-info-metaflac-program-name nil (get-buffer-create emms-tag-editor-log-buffer) nil (append (mapcar (lambda (tag) (concat "--remove-tag=" tag)) tags) '("--import-tags-from=-") '("--") (list (emms-track-name track)))))))) (defun emms-tag-editor-tag-ogg (track) "Commit changes to an OGG file according to TRACK." (let (args val) (mapc (lambda (tag) (let ((info-tag (intern (concat "info-" tag)))) (when (> (length (setq val (emms-track-get track info-tag))) 0) (setq args (append (list "-t" (concat (upcase tag) "=" val)) args))))) '("artist" "composer" "performer" "title" "album" "tracknumber" "date" "genre" "note")) (when args (apply #'call-process "vorbiscomment" nil (get-buffer-create emms-tag-editor-log-buffer) nil "-w" (append args (list (emms-track-name track))))))) (defun emms-tag-editor-tag-file (track program tags filename) "Change TAGS in FILE, using PROGRAM. Valid tags are given by `emms-tag-editor-tagfile-functions'." (let (args val) (mapc (lambda (tag) (setq val (emms-track-get track (car tag))) (if (and val (stringp val)) (setq args (append (list (concat "-" (cdr tag)) val) args)))) tags) (apply 'call-process program nil (get-buffer-create emms-tag-editor-log-buffer) nil (nconc args (list filename))))) (defun emms-tag-editor-get-format (track) "Get the format string to use for committing changes to TRACK." (let ((format (assoc (file-name-extension (emms-track-name track)) emms-tag-editor-formats))) (if format (cdr format) (cdr (assoc "default" emms-tag-editor-formats))))) (defun emms-tag-editor-format-track (track) "Return a string representing the info tags contained in TRACK. This string is suitable for inserting into the tags buffer." (let ((format (funcall emms-tag-editor-get-format-function track))) (if (functionp format) (funcall format track) (format-spec format (apply 'format-spec-make ?m (emms-propertize (emms-track-force-description track) 'face 'emms-playlist-track-face 'emms-track (copy-sequence track)) ?f (emms-track-name track) (apply 'append (mapcar (lambda (tag) (list (string-to-char (cdr tag)) (or (emms-track-get track (car tag)) ""))) emms-tag-editor-tags))))))) (defun emms-tag-editor-track-at (&optional pos) "Return a copy of the track at POS. Defaults to point if POS is nil." (let ((track (emms-playlist-track-at pos)) newtrack) (when track (setq newtrack (copy-sequence track)) (emms-track-set newtrack 'position (point-marker)) (emms-track-set newtrack 'orig-track track) newtrack))) (defsubst emms-tag-editor-erase-buffer (&optional buf) "Erase the buffer BUF, and ensure that it exists." (let ((inhibit-read-only t)) (with-current-buffer (get-buffer-create buf) (erase-buffer)))) (defsubst emms-tag-editor-insert-track (track) "Insert TRACK, if it is specified." (and track (insert (emms-tag-editor-format-track track)))) (defsubst emms-tag-editor-display-log-buffer-maybe () "Display the log buffer if it has any contents." (if (> (buffer-size (get-buffer emms-tag-editor-log-buffer)) 0) (display-buffer emms-tag-editor-log-buffer))) (defun emms-tag-editor-insert-tracks (tracks) "Insert TRACKS into the tag editor buffer." (save-excursion (emms-tag-editor-erase-buffer emms-tag-editor-log-buffer) (emms-tag-editor-erase-buffer emms-tag-editor-edit-buffer) (set-buffer (get-buffer emms-tag-editor-edit-buffer)) (mapc 'emms-tag-editor-insert-track tracks) (emms-tag-editor-mode) (pop-to-buffer (current-buffer)) (goto-char (point-min)) (emms-tag-editor-display-log-buffer-maybe))) (defun emms-tag-editor-edit-track (track) "Edit the track at point, or TRACK." (interactive (list (emms-tag-editor-track-at))) (if (null track) (message "No track at point!") (emms-tag-editor-insert-tracks (list track)))) (defun emms-tag-editor-edit-marked-tracks () "Edit all tracks marked in the current buffer." (interactive) (let ((tracks (emms-mark-mapcar-marked-track 'emms-tag-editor-track-at t))) (if (null tracks) (message "No track marked!") (emms-tag-editor-insert-tracks tracks)))) (defun emms-tag-editor-edit () "Edit tags of either the track at point or all marked tracks." (interactive) (if (emms-mark-has-markedp) (emms-tag-editor-edit-marked-tracks) (emms-tag-editor-edit-track (emms-tag-editor-track-at)))) (defvar emms-tag-editor-mode-map (let ((map (make-sparse-keymap))) (define-key map [tab] 'emms-tag-editor-next-field) (define-key map [backtab] 'emms-tag-editor-prev-field) (define-key map "\C-c\C-n" 'emms-tag-editor-next-track) (define-key map "\C-c\C-p" 'emms-tag-editor-prev-track) (define-key map "\C-c\C-c" 'emms-tag-editor-submit-and-exit) (define-key map "\C-c\C-s" 'emms-tag-editor-submit) (define-key map "\C-x\C-s" 'emms-tag-editor-submit) (define-key map "\C-c\C-r" 'emms-tag-editor-set-all) (define-key map "\C-c\C-a" 'emms-tag-editor-replace-in-tag) (define-key map "\C-c\C-t" 'emms-tag-editor-transpose-tag) map) "Keymap for `emms-tag-editor-mode'.") (define-key emms-playlist-mode-map "E" 'emms-tag-editor-edit) (define-derived-mode emms-tag-editor-mode text-mode "Tag-Edit" "Major mode to edit track tags. \\{emms-tag-editor-mode-map}") (defun emms-tag-editor-set-all (tag value) "Set TAG to VALUE in all tracks. If transient-mark-mode is turned on, you can apply the command to a selected region. If `transient-mark-mode' is on and the mark is active, the changes will only take effect on the tracks in the region." (interactive (list (emms-completing-read "Set tag: " (mapcar (lambda (arg) (list (symbol-name (car arg)))) emms-tag-editor-tags) nil t) (read-from-minibuffer "To: "))) (save-excursion (save-restriction (if (and mark-active transient-mark-mode) (narrow-to-region (region-beginning) (region-end))) (goto-char (point-min)) (while (re-search-forward (concat "^" (regexp-quote tag)) nil t) (skip-chars-forward " \t=") (delete-region (point) (line-end-position)) (insert value))))) (defun emms-tag-editor-replace-in-tag (tag from to) "Query and replace text in selected TAG. For example, if the info-title tag is selected, then only perform replacement in title tags. If `transient-mark-mode' is on and the mark is active, the changes will only take effect on the tracks in the region." (interactive (cons (emms-completing-read "Replace in tag: " (mapcar (lambda (arg) (list (symbol-name (car arg)))) emms-tag-editor-tags) nil t) (let ((common (query-replace-read-args (if (and transient-mark-mode mark-active) "Query replace regexp in region" "Query replace regexp") t))) (butlast common 2)))) (let ((overlay (make-overlay (point-min) (1+ (point-min))))) (overlay-put overlay 'face 'match) (unwind-protect (save-excursion (save-restriction (when (and mark-active transient-mark-mode) (narrow-to-region (region-beginning) (region-end)) (deactivate-mark)) (setq tag (concat (regexp-quote tag) "[ \t]+=[ \t]+")) (goto-char (point-min)) (map-y-or-n-p (lambda (match) (move-overlay overlay (match-beginning 0) (match-end 0)) (format "Replace %s to %s" (car match) (cadr match))) (lambda (match) (delete-region (- (point) (length (car match))) (point)) (insert (cadr match))) (lambda () (if (and (save-excursion (re-search-backward tag (line-beginning-position) t)) (not (= (point) (line-end-position))) (re-search-forward from (line-end-position) t)) (list (match-string 0) (cond ((and (listp to) (fboundp (car to)) (funcall (car to) (cdr to) 0))) ((string-match-p "\\\\[&[:digit:]]" to) (match-substitute-replacement to nil nil)) ((stringp to) to) (t (error "Wrong type argument: string or cons cell, %s" to)))) (let (found) (while (and (not found) (re-search-forward tag nil t)) (if (re-search-forward from (line-end-position) t) (setq found t))) (and found (list (match-string 0) (cond ((and (listp to) (fboundp (car to)) (funcall (car to) (cdr to) 0))) ((string-match-p "\\\\[&[:digit:]]" to) (match-substitute-replacement to nil nil)) ((stringp to) to) (t (error "Wrong type argument: string or cons cell, %s" to))))))))))) (delete-overlay overlay)))) (defun emms-tag-editor-transpose-tag (tag1 tag2) "Transpose value of TAG1 and TAG2. If `transient-mark-mode' is on and the mark is active, the changes will only take effect on the tracks in the region." (interactive (let* ((tag1 (intern (emms-completing-read "Tag 1: " (mapcar (lambda (arg) (list (symbol-name (car arg)))) emms-tag-editor-tags) nil t))) (tag2 (intern (emms-completing-read "Tag 2: " (mapcar (lambda (arg) (list (symbol-name (car arg)))) (assq-delete-all tag1 (copy-sequence emms-tag-editor-tags))) nil t)))) (list tag1 tag2))) (save-excursion (save-restriction (if (and mark-active transient-mark-mode) (narrow-to-region (region-beginning) (region-end))) (let* ((emms-playlist-buffer-p t) (tracks (emms-playlist-tracks-in-region (point-min) (point-max))) (inhibit-read-only t) temp) (erase-buffer) (dolist (track (nreverse tracks)) (setq temp (emms-track-get track tag1)) (emms-track-set track tag1 (emms-track-get track tag2)) (emms-track-set track tag2 temp) (emms-track-set track 'tag-modified t) (emms-tag-editor-insert-track track)))))) (defun emms-tag-editor-guess-tag-filename (pattern fullname) "A pattern is a string like \"%a-%t-%y\" which stand for the file name is constructed by artist, title, year with seperator '-'. see `emms-tag-editor-compile-pattern' for detail about pattern syntax. Available tags are list in `emms-tag-editor-tags'. if with prefix argument, the information will extract from full name, otherwise just match in file name. An example to guess tag from file name, which the file directory is the aritist and file name is the title. It can be done like: C-u M-x emms-tag-editor-guess-tag-filename RET %{a:[^/]+}/%{t:[^/]+}\.mp3 RET " (interactive (list (read-from-minibuffer (format "Match in %sfile name(C-h for help): " (if current-prefix-arg "FULL " "")) nil (let ((map (make-sparse-keymap))) (set-keymap-parent map minibuffer-local-map) (define-key map "\C-h" (lambda () (interactive) (with-output-to-temp-buffer "*Help*" (princ "A pattern is a string like \"%a-%t-%y\" which stand for the file name is constructed by artist, title, year with seperator '-'. see `emms-tag-editor-compile-pattern' for detail about pattern syntax. Available tags are: ") (mapc (lambda (tag) (princ (format "\t%s - %S\n" (cdr tag) (car tag)))) emms-tag-editor-tags) (with-current-buffer standard-output (help-mode))))) map)) current-prefix-arg)) (setq pattern (emms-tag-editor-compile-pattern pattern)) (save-excursion (save-restriction (if (and mark-active transient-mark-mode) (narrow-to-region (region-beginning) (region-end))) (let* ((emms-playlist-buffer-p t) (tracks (emms-playlist-tracks-in-region (point-min) (point-max))) (inhibit-read-only t) filename) (erase-buffer) (dolist (track (nreverse tracks)) (emms-track-set track 'tag-modified t) (setq filename (emms-track-name track)) (or fullname (setq filename (file-name-nondirectory filename))) (when (string-match (car pattern) filename) (mapc (lambda (pair) (emms-track-set track (car (rassoc (char-to-string (car pair)) emms-tag-editor-tags)) (match-string (cdr pair) filename))) (cdr pattern))) (emms-tag-editor-insert-track track)))))) (defun emms-tag-editor-compile-pattern (pattern) "A pattern to regexp convertor. \"%a-%{b:[a-z]+}\" will compile to \"\\([^-]+\\)-\\([a-z]+\\)\"." (let ((index 0) (paren 0) (i 0) (len (length pattern)) (compiled "") registers register match escape c) (while (< i len) (setq c (aref pattern i) i (1+ i)) (cond ((= c ?\\) (setq c (aref pattern i) i (1+ i)) (cond ((= c ?\() (setq paren (1+ paren) index (1+ index))) ((= c ?\)) (setq paren (1- paren)))) (setq compiled (concat compiled "\\" (char-to-string c)))) ((= c ?%) (setq c (aref pattern i) i (1+ i)) ;; How to repressent } in the pattern? (if (= c ?{) (if (/= (aref pattern (1+ i)) ?:) (error "Compile error") (setq register (aref pattern i) match "" i (+ i 2)) (while (and (< i len) (or escape (/= (aref pattern i) ?}))) (if escape (setq escape nil) (if (= (aref pattern i) ?\\) (setq escape t))) (setq match (concat match (char-to-string (aref pattern i))) i (1+ i))) (setq i (1+ i))) (setq register c match "[^-]+")) (setq compiled (concat compiled "\\(" match "\\)") index (1+ index)) (add-to-list 'registers (cons register index))) (t (setq compiled (concat compiled (char-to-string c)))))) (if (/= paren 0) (error "Paren not match!")) (cons compiled registers))) (defun emms-tag-editor-next-field (arg) "Move to the next tag field." (interactive "p") (if (> arg 0) (re-search-forward "\\s-*=[ \t]*" nil nil arg) (emms-tag-editor-prev-field (- arg)))) (defun emms-tag-editor-prev-field (arg) "Move to the previous tag field." (interactive "p") (if (< arg 0) (emms-tag-editor-next-field (- arg)) (skip-chars-backward " \t=") (re-search-backward "\\s-*=[ \t]*" nil nil arg) (skip-chars-forward " \t="))) (defun emms-tag-editor-prev-track () "Move to the previous track." (interactive) (let ((prev (previous-single-property-change (point) 'emms-track))) (when (not prev) (error "No previous track")) (when (not (get-text-property prev 'emms-track)) (setq prev (or (previous-single-property-change prev 'emms-track) (point-min)))) (when (or (not prev) (not (get-text-property prev 'emms-track))) (error "No previous track")) (goto-char prev))) (defun emms-tag-editor-next-track () "Move to the next track." (interactive) (let ((next (next-single-property-change (point) 'emms-track))) (when (not next) (error "No next track")) (when (not (get-text-property next 'emms-track)) (setq next (next-single-property-change next 'emms-track))) (when (or (not next) (= next (point-max))) (error "No next track")) (goto-char next))) (defun emms-tag-editor-submit (arg) "Make modified tags take affect. With prefix argument, bury the tag edit buffer." (interactive "P") (let ((tracks (funcall emms-tag-editor-parse-function))) (if (not (and tracks (y-or-n-p "Submit changes? "))) (message "No tags were modified") (emms-tag-editor-erase-buffer emms-tag-editor-log-buffer) (emms-tag-editor-apply tracks))) (if arg (bury-buffer))) (defun emms-tag-editor-apply (tracks) "Apply all changes made to TRACKS." (message "Setting tags...") (let (filename func exit old pos val need-sync) (save-excursion (dolist (track tracks) (when (emms-track-get track 'tag-modified) (setq filename (emms-track-name track) old (emms-track-get track 'orig-track)) ;; rename local file (when (and (emms-track-get track 'newname) (eq (emms-track-get track 'type) 'file) (file-writable-p (emms-track-name track)) (y-or-n-p (format "Rename %s to %s? " (emms-track-name track) (emms-track-get track 'newname)))) (setq filename (emms-track-get track 'newname)) (ignore-errors ;; Ignore errors so that renaming multiple files doesn't stop ;; because of one that fails. In that case it's probably ;; old-file = newfile which causes the problem. (rename-file (emms-track-name track) filename 1)) (emms-track-set old 'name filename) ;; for re-enter this function (emms-track-set track 'name filename) (setq need-sync t) ;; register to emms-cache-db (when (boundp 'emms-cache-modified-function) (funcall emms-cache-modified-function) (funcall emms-cache-set-function 'file filename old))) (emms-track-set track 'newname nil) ;; set tags to original track (dolist (tag emms-tag-editor-tags) (when (setq val (emms-track-get track (car tag))) (emms-track-set old (car tag) val))) ;; 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) emms-tag-editor-tagfile-functions))) (setq exit (if (functionp (cdr func)) (funcall (cdr func) track) (emms-tag-editor-tag-file track (cadr func) (nth 2 func) filename))) (if (zerop exit) (emms-track-get track 'info-mtime (butlast (current-time))) (emms-tag-editor-log "Changing tags of %s failed with exit value %d" filename exit))) ;; update track in playlist (when (and (setq pos (emms-track-get track 'position)) (marker-position pos)) (set-buffer (marker-buffer pos)) (goto-char pos) (funcall emms-playlist-update-track-function)) ;; clear modified tag (emms-track-set track 'tag-modified nil)))) (if (and (featurep 'emms-cache) need-sync (y-or-n-p "You have changed some track names; sync the cache? ")) (and (fboundp 'emms-cache-sync) ; silence byte-compiler (emms-cache-sync))) (unless (emms-tag-editor-display-log-buffer-maybe) (message "Setting tags...done")))) (defun emms-tag-editor-submit-and-exit () "Submit changes to track information and exit the tag editor." (interactive) (emms-tag-editor-submit t)) (defun emms-tag-editor-default-parser () "Default function used to parse tags in `emms-tag-editor-edit-buffer'." (let (next tracks track key val) (goto-char (point-min)) (if (get-text-property (point) 'emms-track) (setq next (point)) (setq next (next-single-property-change (point) 'emms-track))) (when next (while (progn (goto-char next) (setq track (get-text-property (point) 'emms-track)) (forward-line 1) (mapc (lambda (pair) (when (string-match "\\s-*=\\s-*" pair) (setq key (intern-soft (substring pair 0 (match-beginning 0))) val (substring pair (match-end 0))) (when (and key (let ((old (emms-track-get track key))) (if old (not (string= val old)) (string< "" val)))) (if (eq key 'name) (emms-track-set track 'newname val) (emms-track-set track key val)) (emms-track-set track 'tag-modified t)))) (let ((end-point (next-single-property-change (point) 'emms-track))) (if (and end-point (save-excursion (goto-char end-point) (bolp))) (setq next end-point) (progn (setq next nil end-point (point-max)))) (split-string (buffer-substring (point) end-point) "\n"))) (if (emms-track-get track 'tag-modified) (push track tracks)) next)) tracks))) (defun emms-tag-editor-log (&rest args) (with-current-buffer (get-buffer-create emms-tag-editor-log-buffer) (goto-char (point-max)) (insert (apply 'format args) "\n"))) ;; ;; Renaming files according their tags ;; (defvar emms-tag-editor-rename-format "%a - %l - %n - %t" "When `emms-tag-editor-rename' is invoked the track's file will be renamed according this format specification. The file extension will be added automatically. It uses the format specs defined in `emms-tag-editor-tags'.") (defun emms-tag-editor-rename () "Rename the file corresponding to track at point or all marked tracks according to the value of `emms-tag-editor-rename-format'." (interactive) (if (emms-mark-has-markedp) (emms-tag-editor-rename-marked-tracks) (emms-tag-editor-rename-track (emms-tag-editor-track-at)))) (defun emms-tag-editor-rename-track (track &optional dont-apply) "Rename TRACK's file according `emms-tag-editor-rename-format's value. If DONT-APPLY is non-nil the changes won't be applied directly. Then it's the callers job to apply them afterwards with `emms-tag-editor-apply'." (if (eq (emms-track-get track 'type) 'file) (let* ((old-file (emms-track-name track)) (path (file-name-directory old-file)) (suffix (file-name-extension old-file)) (new-file (concat path (format-spec emms-tag-editor-rename-format (apply 'format-spec-make (apply 'append (mapcar (lambda (tag) (list (string-to-char (cdr tag)) (or (emms-track-get track (car tag)) ""))) emms-tag-editor-tags)))) "." suffix))) (emms-track-set track 'newname new-file) (emms-track-set track 'tag-modified t) (unless dont-apply (emms-tag-editor-apply (list track)))) (message "Only files can be renamed."))) (defun emms-tag-editor-rename-marked-tracks () "Rename the files corresponding to all marked tracks according `emms-tag-editor-rename-format's value." (let ((tracks (emms-mark-mapcar-marked-track 'emms-tag-editor-track-at t))) (if (null tracks) (message "No track marked!") (dolist (track tracks) (emms-tag-editor-rename-track track t)) (emms-tag-editor-apply tracks)))) (define-key emms-playlist-mode-map "R" 'emms-tag-editor-rename) (provide 'emms-tag-editor) ;;; Emms-tag-editor.el ends here ��������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������emms-6.00/emms-url.el�������������������������������������������������������������������������������0000664�0001750�0001750�00000007731�13746063641�012703� 0����������������������������������������������������������������������������������������������������ustar �yrk�����������������������������yrk��������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������;;; emms-url.el --- Make URL and EMMS work together well ;; Copyright (C) 2006, 2007, 2008, 2009 Free Software Foundation, Inc. ;; 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, 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; see the file COPYING. If not, write to the ;; Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, ;; Boston, MA 02110-1301, USA. ;;; Commentary: ;; These routines sanify input to URL and parse data returned by URL. ;;; Code: (require 'url) (require 'emms-compat) (defvar emms-url-specials-entire '((?\ . "%20") (?\n . "%0D%0A")) "*An alist of characters which must be represented specially in URLs. The transformation is the key of the pair. This is used by `emms-url-quote-entire'.") (defun emms-url-quote-entire (url) "Escape specials conservatively in an entire URL. The specials to escape are specified by the `emms-url-specials-entire' variable. If you want to escape parts of URLs thoroughly, then use `emms-url-quote' instead." (apply (function concat) (mapcar (lambda (ch) (let ((repl (assoc ch emms-url-specials-entire))) (if (null repl) (char-to-string ch) (cdr repl)))) (append url nil)))) (defun emms-url-quote (s &optional safe) "Replace special characters in S using the `%xx' escape. This is useful for escaping parts of URLs, but not entire URLs. Characters in [a-zA-Z_.-/] and SAFE(default is \"\") will never be quoted. e.g., (emms-url-quote \"abc def\") => \"abc%20def\"." (if (not (stringp s)) "" (or safe (setq safe "")) (save-match-data (let ((re (if (string-match "]" safe) ;; `]' should be placed at the beginning inside [] (format "[]a-zA-Z_.-/%s]" (emms-replace-regexp-in-string "]" "" safe)) (format "[a-zA-Z_.-/%s]" safe)))) (mapconcat (lambda (c) (let ((s1 (char-to-string c))) (if (string-match re s1) s1 (format "%%%02x" c)))) (string-to-list (encode-coding-string s 'utf-8)) ""))))) (defun emms-url-quote-plus (s &optional safe) "Run (emms-url-quote s \" \"), then replace ` ' with `+'." (emms-replace-regexp-in-string " " "+" (emms-url-quote s (concat safe " ")))) (defun emms-url-quote-underscore (s &optional safe) "Run (emms-url-quote s \" \"), then replace ` ' with `_'." (emms-replace-regexp-in-string " " "_" (emms-url-quote s (concat safe " ")))) (defun emms-http-content-coding () (save-match-data (and (boundp 'url-http-content-type) (stringp url-http-content-type) (string-match ";\\s-*charset=\\([^;[:space:]]+\\)" url-http-content-type) (intern-soft (downcase (match-string 1 url-http-content-type)))))) (defun emms-http-decode-buffer (&optional buffer) "Recode the buffer with `url-retrieve's contents. Else the buffer would contain multibyte chars like \\123\\456." (with-current-buffer (or buffer (current-buffer)) (let* ((default (or (car default-process-coding-system) 'utf-8)) (coding (or (emms-http-content-coding) default))) (when coding ;; (pop-to-buffer (current-buffer)) ;; (message "content-type: %s" url-http-content-type) ;; (message "coding: %S [default: %S]" coding default) (set-buffer-multibyte t) (decode-coding-region (point-min) (point-max) coding))))) (provide 'emms-url) ;;; emms-url.el ends here ���������������������������������������emms-6.00/emms-volume-amixer.el���������������������������������������������������������������������0000664�0001750�0001750�00000005272�13746063641�014671� 0����������������������������������������������������������������������������������������������������ustar �yrk�����������������������������yrk��������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������;;; emms-volume-amixer.el --- a mode for changing volume using amixer ;; Copyright (C) 2006, 2007, 2008, 2009 Free Software Foundation, Inc. ;; Author: Martin Schoenmakers <aiviru@diamond-age.net> ;; 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, 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; see the file COPYING. If not, write to the ;; Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, ;; Boston, MA 02110-1301, USA. ;;; Commentary: ;; This file defines a few simple functions to raise or lower the volume ;; using amixer. It can be used stand-alone, though it's meant for usage ;; with EMMS, particularly with emms-volume.el ;;; History: ;; May 30 2006: First cleanup and collation of amixer functions into a ;; separate file for releasability. ;;; Todo: ;; There probably needs to be more configurability, which may in turn ;; mean adding some more functions. ;; Some of this could benefit from adding customize interfaces. ;;; Code: (defcustom emms-volume-amixer-control "Master" "The control to change the volume with. Controls includes \"Master\", \"PCM\", etc. For a full list of available controls, run `amixer controls' in a shell." :type '(choice (const :tag "Master" "Master") (const :tag "PCM" "PCM") (string :tag "Something else: ")) :group 'emms-volume) (defcustom emms-volume-amixer-card 0 "The card number to change volume. The card is identified by a number. For a full list run `cat /proc/asound/cards' in a shell." :type 'integer :group 'emms-volume) ;;;###autoload (defun emms-volume-amixer-change (amount) "Change amixer master volume by AMOUNT." (message "Playback channels: %s" (with-temp-buffer (when (zerop (call-process "amixer" nil (current-buffer) nil "-c" (format "%d" emms-volume-amixer-card) "sset" emms-volume-amixer-control (format "%d%%%s" (abs amount) (if (< amount 0) "-" "+")))) (if (re-search-backward "\\[\\([0-9]+%\\)\\]" nil t) (match-string 1)))))) (provide 'emms-volume-amixer) ;;; emms-volume-amixer.el ends here ��������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������emms-6.00/emms-volume-mixerctl.el�������������������������������������������������������������������0000664�0001750�0001750�00000005505�13746063641�015232� 0����������������������������������������������������������������������������������������������������ustar �yrk�����������������������������yrk��������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������;;; emms-volume-mixerctl.el --- a mode for changing volume using mixerctl ;; Copyright (C) 2006, 2007, 2008, 2009, 2019 Free Software Foundation, Inc. ;; Authors: Martin Schoenmakers <aiviru@diamond-age.net> ;; Bruno Félix Rezende Ribeiro <oitofelix@gnu.org> ;; 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, 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; see the file COPYING. If not, write to the ;; Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, ;; Boston, MA 02110-1301, USA. ;;; Commentary: ;; This file defines a few simple functions to raise or lower the volume ;; using mixerctl. It can be used stand-alone, though it's meant for usage ;; with EMMS, particularly with emms-volume.el ;;; History: ;; Jul 06 2019: Based on emms-volume-amixer.el by Martin Schoenmakers ;;; Todo: ;; There probably needs to be more configurability, which may in turn ;; mean adding some more functions. ;; Some of this could benefit from adding customize interfaces. ;;; Code: (defcustom emms-volume-mixerctl-control "master" "The control to change the volume with. Controls includes \"master\", \"mono\", etc. For a full list of available controls, run `mixerctl -a' in a shell." :type '(choice (const :tag "master" "master") (const :tag "mono" "mono") (string :tag "Something else: ")) :group 'emms-volume) (defcustom emms-volume-mixerctl-card 0 "The card number to change volume. The card is identified by a number. For a full list run `ls /dev/mixer?*' in a shell." :type 'integer :group 'emms-volume) ;;;###autoload (defun emms-volume-mixerctl-change (amount) "Change mixerctl master volume by AMOUNT." (message "Playback channels: %s" (with-temp-buffer (when (zerop (call-process "mixerctl" nil (current-buffer) nil "-f" (format "/dev/mixer%d" emms-volume-mixerctl-card) (let ((amount-str (format "%s%d" (if (< amount 0) "-" "+") (abs amount)))) (format "outputs.%s=%s,%s" emms-volume-mixerctl-control amount-str amount-str)))) (if (and (forward-line -1) (re-search-forward "^\\(.*\\):.*->.*,\\(.*\\)$" nil t)) (format "%s -> %s" (match-string 1) (match-string 2))))))) (provide 'emms-volume-mixerctl) ;;; emms-volume-mixerctl.el ends here �������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������emms-6.00/emms-volume-pulse.el����������������������������������������������������������������������0000664�0001750�0001750�00000007144�13746063641�014534� 0����������������������������������������������������������������������������������������������������ustar �yrk�����������������������������yrk��������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������;;; emms-volume-pulse.el --- a mode for changing volume using PulseAudio pactl ;; Copyright (C) 2015 Free Software Foundation, Inc. ;; Author: Rasmus Pank Roulund <emacs@pank.eu> ;; 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, 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; see the file COPYING. If not, write to the ;; Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, ;; Boston, MA 02110-1301, USA. ;;; Commentary: ;; This file defines a few simple functions to raise or lower the volume ;; using pactl. It can be used stand-alone, though it's meant for usage ;; with EMMS, particularly with emms-volume.el. ;; ;; To use add the following to your EMMS configuration ;; (setq emms-volume-change-function 'emms-volume-pulse-change) ;;; History: ;; Marts 2015: First release. Partly based on emms-volume-amixer.el ;;; Todo: ;; There probably needs to be more configurability, which may in turn ;; mean adding some more functions. ;; Some of this could benefit from adding customize interfaces. ;;; Code: (require 'cl-lib) ;; TODO: it would be great if custom could have ;; choices based on pactl list short sinks | cut -f1-2 (defcustom emms-volume-pulse-sink 0 "The sink to use for volume adjustment. See full list of devices on your system by running pactl list short sinks" :type '(choice (number :tag "Sink number") (string :tag "Sink symbolic name")) :group 'emms-volume) (defcustom emms-volume-pulse-max-volume 100 "The maximum volume percentage." :type 'integer :group 'emms-volume) (defun emms-volume--pulse-get-volume () "Return `emms-volume-pulse-sink' volume." (let ((sink-number-p (numberp emms-volume-pulse-sink)) (start 0) (output (shell-command-to-string (concat "pactl list sinks" "|" "grep -E -e 'Sink' -e 'Name' -e '^[^a-zA-Z]*Volume'")))) (string-to-number (car (reverse (funcall (if sink-number-p 'assq 'assoc) emms-volume-pulse-sink (mapcar (if sink-number-p 'identity 'cdr) (cl-loop while (string-match (mapconcat 'identity '(".*Sink[ \t]+\\#\\([0-9]+\\)" ".*Name:[ \t]\\([^\n]+\\)" ".*Volume:.*?\\([0-9]+\\)%.*\n?") "\n") output) collect (list (string-to-number (match-string 1 output)) (match-string 2 output) (match-string 3 output)) do (setq output (replace-match "" nil nil output)))))))))) ;;;###autoload (defun emms-volume-pulse-change (amount) "Change PulseAudio volume by AMOUNT." (message "Volume is %s%%" (let ((pactl (or (executable-find "pactl") (error "pactl is not in PATH"))) (next-vol (max (min (+ (emms-volume--pulse-get-volume) amount) emms-volume-pulse-max-volume) 0))) (when (zerop (shell-command (format "%s set-sink-volume %s %s%%" pactl emms-volume-pulse-sink next-vol))) next-vol)))) (provide 'emms-volume-pulse) ;;; emms-volume-pulse.el ends here ����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������emms-6.00/emms-volume.el����������������������������������������������������������������������������0000664�0001750�0001750�00000012361�13746063641�013403� 0����������������������������������������������������������������������������������������������������ustar �yrk�����������������������������yrk��������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������;;; emms-volume.el --- Volume functions and a minor mode to adjust volume easily ;; Copyright (C) 2006, 2007, 2008, 2009 Free Software Foundation, Inc. ;; Author: Martin Schoenmakers <aiviru@diamond-age.net> ;; Bruno Félix Rezende Ribeiro <oitofelix@gnu.org> ;; 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, 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; see the file COPYING. If not, write to the ;; Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, ;; Boston, MA 02110-1301, USA. ;;; Commentary: ;; ;; This file provides generally two things: ;; Generic volume setting functions and some appropriate bindings for EMMS ;; playlist buffers. These can also be bound to global keys,however, the ;; second part may be more useful for this. This part provides functions ;; meant to be bound to a global key (the author uses C-c e + and C-c e -), ;; which then temporarily activates a minor mode allowing you to change the ;; volume with just + and -. This mode deactivates a short (configurable) ;; amount of time after the last volume change. This allows for easier volume ;; adjustment without getting in the way. ;;; History: ;; May 2006: First stab at writing the minor mode. ;; ;; 30 May 2006: Cleanup and restructuring to fit with EMMS. ;;; Todo: ;; Some of this could benefit from adding customize interfaces. ;;; Code: (require 'emms) (require 'emms-playlist-mode) (require 'emms-volume-amixer) (require 'emms-volume-pulse) (require 'emms-volume-mixerctl) ;; Customize group (defgroup emms-volume nil "Volume setting for EMMS." :group 'emms) ;; General volume setting related code. (defcustom emms-volume-change-function (cond ((executable-find "amixer") 'emms-volume-amixer-change) ((executable-find "pactl") 'emms-volume-pulse-change) ((executable-find "mixerctl") 'emms-volume-mixerctl-change) (t #'(lambda (amount) (user-error "%s" "No supported mixer found. Please, define ‘emms-volume-change-function’.")))) "*The function to use to change the volume. If you have your own functions for changing volume, set this." :type '(choice (const :tag "Amixer" emms-volume-amixer-change) (const :tag "MPD" emms-volume-mpd-change) (const :tag "PulseAudio" emms-volume-pulse-change) (const :tag "Mixerctl" emms-volume-mixerctl-change) (function :tag "Lisp function")) :group 'emms-volume) (defcustom emms-volume-change-amount 2 "The amount to use when raising or lowering the volume using the emms-volume interface. This should be a positive integer." :type 'integer :group 'emms-volume) ;;;###autoload (defun emms-volume-raise () "Raise the speaker volume." (interactive) (funcall emms-volume-change-function emms-volume-change-amount)) ;;;###autoload (defun emms-volume-lower () "Lower the speaker volume." (interactive) (funcall emms-volume-change-function (- emms-volume-change-amount))) (define-key emms-playlist-mode-map (kbd "+") 'emms-volume-raise) (define-key emms-playlist-mode-map (kbd "-") 'emms-volume-lower) ;; Code specific to the minor mode. (define-minor-mode emms-volume-minor-mode "Allows volume setting with + and - after an initial key combo." :global t :init-value nil :lighter " (+/-)" :keymap '(("+" . emms-volume-mode-plus) ("-" . emms-volume-mode-minus))) (defvar emms-volume-mode-timeout 2 "*The timeout in amount of seconds used by `emms-volume-minor-mode'.") (defvar emms-volume-mode-timer nil "The timer `emms-volume-minor-mode' uses.") ;;;###autoload (defun emms-volume-mode-plus () "Raise volume and enable or extend the `emms-volume-minor-mode' timeout." (interactive) (emms-volume-raise) (emms-volume-mode-start-or-extend)) ;;;###autoload (defun emms-volume-mode-minus () "Lower volume and enable or extend the `emms-volume-minor-mode' timeout." (interactive) (emms-volume-lower) (emms-volume-mode-start-or-extend)) (defun emms-volume-mode-disable-timer () "Disable `emms-volume-minor-mode' timer." (cancel-timer emms-volume-mode-timer) (setq emms-volume-mode-timer nil)) (defun emms-volume-mode-set-timer () "Set a new `emms-volume-minor-mode' timer." (when emms-volume-mode-timer (emms-volume-mode-disable-timer)) (setq emms-volume-mode-timer (run-at-time emms-volume-mode-timeout nil 'emms-volume-mode-timer-timeout))) (defun emms-volume-mode-timer-timeout () "Function to disable `emms-volume-minor-mode' at timeout." (setq emms-volume-mode-timer nil) (emms-volume-minor-mode -1)) (defun emms-volume-mode-start-or-extend () "Start `emms-volume-minor-mode' or extend its running time." (when (null emms-volume-minor-mode) (emms-volume-minor-mode 1)) (emms-volume-mode-set-timer)) (provide 'emms-volume) ;;; emms-volume.el ends here �������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������emms-6.00/emms.el�����������������������������������������������������������������������������������0000664�0001750�0001750�00000151151�13746063641�012077� 0����������������������������������������������������������������������������������������������������ustar �yrk�����������������������������yrk��������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������;;; emms.el --- The Emacs Multimedia System ;; Copyright (C) 2003, 2004, 2005, 2006, 2007, 2008, ;; 2009, 2018, 2020 Free Software Foundation, Inc. ;; Author: Jorgen Schäfer <forcer@forcix.cx>, the Emms developers (see AUTHORS file) ;; Maintainer: Yoni Rabkin <yrk@gnu.org> ;; Version: 6.00 ;; Keywords: emms, mp3, ogg, flac, music, mpeg, video, multimedia ;; Package-Type: multi ;; Package-Requires: ((cl-lib "0.5")) ;; url: https://www.gnu.org/software/emms/ ;; 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, 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 this program. If not, see <https://www.gnu.org/licenses/>. ;;; Commentary: ;; This is the very core of EMMS. It provides ways to play a track ;; using `emms-start', to go through the playlist using the commands ;; `emms-next' and `emms-previous', to stop the playback using ;; `emms-stop', and to see what's currently playing using `emms-show'. ;; But in itself, this core is useless, because it doesn't know how to ;; play any tracks --- you need players for this. In fact, it doesn't ;; even know how to find any tracks to consider playing --- for this, ;; you need sources. ;; A sample configuration is offered in emms-setup.el, and the ;; Friendly Manual in the doc/ directory is both detailed, and kept up ;; to date. ;;; Code: (defvar emms-version "6.00" "EMMS version string.") ;;; User Customization (defgroup emms nil "*The Emacs Multimedia System." :prefix "emms-" :group 'multimedia :group 'applications) (defgroup emms-player nil "*Track players for EMMS." :prefix "emms-player-" :group 'emms) (defgroup emms-source nil "*Track sources for EMMS." :prefix "emms-source-" :group 'emms) (defcustom emms-player-list nil "*List of players that EMMS can use. You need to set this!" :group 'emms :type '(repeat (symbol :tag "Player"))) (defcustom emms-show-format "Currently playing: %s" "*The format to use for `emms-show'. Any \"%s\" is replaced by what `emms-track-description-function' returns for the currently playing track." :group 'emms :type 'string) (defcustom emms-repeat-playlist nil "*Non-nil if the EMMS playlist should automatically repeat. If nil, playback will stop when the last track finishes playing. If non-nil, EMMS will wrap back to the first track when that happens." :group 'emms :type 'boolean) (defcustom emms-random-playlist nil "*Non-nil means that tracks are played randomly. If nil, tracks are played sequentially." :group 'emms :type 'boolean) (defcustom emms-repeat-track nil "Non-nil, playback will repeat current track. If nil, EMMS will play track by track normally." :group 'emms :type 'boolean) (defvar-local emms-single-track nil "Non-nil, play the current track and then stop.") (defcustom emms-completing-read-function (if (and (boundp 'ido-mode) ido-mode) 'ido-completing-read 'completing-read) "Function to call when prompting user to choose between a list of options. This should take the same arguments as `completing-read'. Some possible values are `completing-read' and `ido-completing-read'. Note that you must set `ido-mode' if using `ido-completing-read'." :group 'emms :type 'function) (defcustom emms-track-description-function 'emms-track-simple-description "*Function for describing an EMMS track in a user-friendly way." :group 'emms :type 'function) (defcustom emms-player-delay 0 "The delay to pause after a player finished. This is a floating-point number of seconds. This is necessary for some platforms where it takes a bit to free the audio device after a player has finished. If EMMS is skipping songs, increase this number." :type 'number :group 'emms) (defcustom emms-playlist-shuffle-function 'emms-playlist-simple-shuffle "*The function to use for shuffling the playlist." :type 'function :group 'emms) (defcustom emms-playlist-sort-function 'emms-playlist-simple-sort "*The function to use for sorting the playlist." :type 'function :group 'emms) (defcustom emms-playlist-uniq-function 'emms-playlist-simple-uniq "*The function to use for removing duplicate tracks in the playlist." :type 'function :group 'emms) (defcustom emms-sort-lessp-function 'emms-sort-track-name-less-p "*Function for comparing two EMMS tracks. The function should return non-nil if and only if the first track sorts before the second (see `sort')." :group 'emms :type 'function) (defcustom emms-playlist-buffer-name " *EMMS Playlist*" "*The default name of the EMMS playlist buffer." :type 'string :group 'emms) (defcustom emms-playlist-default-major-mode 'emms-playlist-mode "*The default major mode for EMMS playlist." :type 'function :group 'emms) (defcustom emms-playlist-insert-track-function 'emms-playlist-simple-insert-track "*A function to insert a track into the playlist buffer." :group 'emms :type 'function) (make-variable-buffer-local 'emms-playlist-insert-track-function) (defcustom emms-playlist-update-track-function 'emms-playlist-simple-update-track "*A function to update the track at point. This is called when the track information changed. This also shouldn't assume that the track has been inserted before." :group 'emms :type 'function) (make-variable-buffer-local 'emms-playlist-insert-track-function) (defcustom emms-playlist-delete-track-function 'emms-playlist-simple-delete-track "*A function to delete the track at point in the playlist buffer." :group 'emms :type 'function) (make-variable-buffer-local 'emms-playlist-delete-track-function) (defcustom emms-ok-track-function 'emms-default-ok-track-function "*Function returns true if we shouldn't skip this track." :group 'emms :type 'function) (defcustom emms-playlist-source-inserted-hook nil "*Hook run when a source got inserted into the playlist. The buffer is narrowed to the new tracks." :type 'hook :group 'emms) (defcustom emms-playlist-selection-changed-hook nil "*Hook run after another track is selected in the EMMS playlist." :group 'emms :type 'hook) (defcustom emms-playlist-cleared-hook nil "*Hook run after the current EMMS playlist is cleared. This happens both when the playlist is cleared and when a new buffer is created for it." :group 'emms :type 'hook) (defcustom emms-track-initialize-functions nil "*List of functions to call for each new EMMS track. This can be used to initialize tracks with various info." :group 'emms :type 'hook) (defcustom emms-track-info-filters nil "*List of functions to call when a track changes data, before updating the display. These functions are passed the track as an argument." :group 'emms :type 'hook) (defcustom emms-track-updated-functions nil "*List of functions to call when a track changes data, after updating the display. These functions are passed the track as an argument." :group 'emms :type 'hook) (defcustom emms-player-started-hook nil "*Hook run when an EMMS player starts playing." :group 'emms :type 'hook :options '(emms-show)) (defcustom emms-player-stopped-hook nil "*Hook run when an EMMS player is stopped by the user. See `emms-player-finished-hook'." :group 'emms :type 'hook) (defcustom emms-player-finished-hook nil "*Hook run when an EMMS player finishes playing a track. Please pay attention to the differences between `emms-player-finished-hook' and `emms-player-stopped-hook'. The former is called only when the player actually finishes playing a track; the latter, only when the player is stopped interactively." :group 'emms :type 'hook) (defcustom emms-player-next-function 'emms-next-noerror "*A function run when EMMS thinks the next song should be played." :group 'emms :type 'function :options '(emms-next-noerror emms-random)) (defcustom emms-player-paused-hook nil "*Hook run when a player is paused or resumed. Use `emms-player-paused-p' to find the current state." :group 'emms :type 'hook) (defcustom emms-seek-seconds 10 "The number of seconds to seek forward or backward when seeking." :group 'emms :type 'number) (defcustom emms-player-seeked-functions nil "*Functions called when a player is seeking. The functions are called with a single argument, the amount of seconds the player did seek." :group 'emms :type 'hook) (defcustom emms-player-time-set-functions nil "*Functions called when a player is setting the elapsed time of a track. The functions are called with a single argument, the time elapsed since the beginning of the current track." :group 'emms :type 'hook) (defcustom emms-cache-get-function nil "A function to retrieve a track entry from the cache. This is called with two arguments, the type and the name." :group 'emms :type 'function) (defcustom emms-cache-set-function nil "A function to add/set a track entry from the cache. This is called with three arguments: the type of the track, the name of the track, and the track itself." :group 'emms :type 'function) (defcustom emms-cache-modified-function nil "A function to be called when a track is modified. The modified track is passed as the argument to this function." :group 'emms :type 'function) (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) (defvar emms-player-playing-p nil "The currently playing EMMS player, or nil.") (defvar emms-player-paused-p nil "Whether the current player is paused or not.") (defvar emms-source-old-buffer nil "The active buffer before a source was invoked. This can be used if the source depends on the current buffer not being the playlist buffer.") (defvar emms-playlist-buffer nil "The current playlist buffer, if any.") ;;; Macros ;;; These need to be at the top of the file so that compilation works. (defmacro with-current-emms-playlist (&rest body) "Run BODY with the current buffer being the current playlist buffer. This also disables any read-onliness of the current buffer." `(progn (when (or (not emms-playlist-buffer) (not (buffer-live-p emms-playlist-buffer))) (emms-playlist-current-clear)) (let ((emms-source-old-buffer (or emms-source-old-buffer (current-buffer)))) (with-current-buffer emms-playlist-buffer (let ((inhibit-read-only t)) ,@body))))) (put 'with-current-emms-playlist 'lisp-indent-function 0) (put 'with-current-emms-playlist 'edebug-form-spec '(body)) (defmacro emms-with-inhibit-read-only-t (&rest body) "Simple wrapper around `inhibit-read-only'." `(let ((inhibit-read-only t)) ,@body)) (put 'emms-with-inhibit-read-only-t 'edebug-form-spec '(body)) (defmacro emms-with-widened-buffer (&rest body) `(save-restriction (widen) ,@body)) (put 'emms-with-widened-buffer 'edebug-form-spec '(body)) (defmacro emms-walk-tracks (&rest body) "Execute BODY for each track in the current buffer, starting at point. Point will be placed at the beginning of the track before executing BODY. Point will not be restored afterward." (let ((donep (make-symbol "donep"))) `(let ((,donep nil)) ;; skip to first track if not on one (unless (emms-playlist-track-at (point)) (condition-case nil (emms-playlist-next) (error (setq ,donep t)))) ;; walk tracks (while (not ,donep) ,@body (condition-case nil (emms-playlist-next) (error (setq ,donep t))))))) (put 'emms-walk-tracks 'lisp-indent-function 0) (put 'emms-walk-tracks 'edebug-form-spec '(body)) (defvar emms-player-base-format-list '("ogg" "mp3" "wav" "mpg" "mpeg" "wmv" "wma" "mov" "avi" "divx" "ogm" "ogv" "asf" "mkv" "rm" "rmvb" "mp4" "flac" "vob" "m4a" "ape" "flv" "webm" "aif") "A list of common formats which player definitions can use.") ;;; User Interface (defun emms-start () "Start playing the current track in the EMMS playlist." (interactive) (unless emms-player-playing-p (emms-player-start (emms-playlist-current-selected-track)))) (defun emms-stop () "Stop any current EMMS playback." (interactive) (when emms-player-playing-p (emms-player-stop))) (defun emms-next () "Start playing the next track in the EMMS playlist. This might behave funny if called from `emms-player-next-function', so use `emms-next-noerror' in that case." (interactive) (when emms-player-playing-p (emms-stop)) (emms-playlist-current-select-next) (emms-start)) (defun emms-next-noerror () "Start playing the next track in the EMMS playlist. Unlike `emms-next', this function doesn't signal an error when called at the end of the playlist. This function should only be called when no player is playing. This is a good function to put in `emms-player-next-function'." (interactive) (when emms-player-playing-p (error "A track is already being played")) (cond (emms-repeat-track (emms-start)) (emms-single-track ; buffer local (emms-stop)) ;; attempt to play the next track but ignore errors ((condition-case nil (progn (emms-playlist-current-select-next) t) (error nil)) (if (funcall emms-ok-track-function (emms-playlist-current-selected-track)) (emms-start) (emms-next-noerror))) (t (message "No next track in playlist")))) (defun emms-previous () "Start playing the previous track in the EMMS playlist." (interactive) (when emms-player-playing-p (emms-stop)) (emms-playlist-current-select-previous) (emms-start)) (defun emms-random () "Jump to a random track." (interactive) (when emms-player-playing-p (emms-stop)) (emms-playlist-current-select-random) (emms-start)) (defun emms-pause () "Pause the current player. If player hasn't started, then start it now." (interactive) (if emms-player-playing-p (emms-player-pause) (emms-start))) (defun emms-seek (seconds) "Seek the current player SECONDS seconds. This can be a floating point number for sub-second fractions. It can also be negative to seek backwards." (interactive "nSeconds to seek: ") (emms-ensure-player-playing-p) (emms-player-seek seconds)) (defun emms-seek-to (seconds) "Seek the current player to SECONDS seconds. This can be a floating point number for sub-second fractions. It can also be negative to seek backwards." (interactive "nSeconds to seek to: ") (emms-ensure-player-playing-p) (emms-player-seek-to seconds)) (defun emms-seek-forward () "Seek ten seconds forward." (interactive) (when emms-player-playing-p (emms-player-seek emms-seek-seconds))) (defun emms-seek-backward () "Seek ten seconds backward." (interactive) (when emms-player-playing-p (emms-player-seek (- emms-seek-seconds)))) (defun emms-show (&optional insertp) "Describe the current EMMS track in the minibuffer. If INSERTP is non-nil, insert the description into the current buffer instead. This function uses `emms-show-format' to format the current track." (interactive "P") (let ((string (if emms-player-playing-p (format emms-show-format (emms-track-description (emms-playlist-current-selected-track))) "Nothing playing right now"))) (if insertp (insert string) (message "%s" string)))) (defun emms-shuffle () "Shuffle the current playlist. This uses `emms-playlist-shuffle-function'." (interactive) (with-current-emms-playlist (save-excursion (funcall emms-playlist-shuffle-function)))) (defun emms-sort () "Sort the current playlist. This uses `emms-playlist-sort-function'." (interactive) (with-current-emms-playlist (save-excursion (funcall emms-playlist-sort-function)))) (defun emms-uniq () "Remove duplicates from the current playlist. This uses `emms-playlist-uniq-function'." (interactive) (with-current-emms-playlist (save-excursion (funcall emms-playlist-uniq-function)))) (defun emms-toggle-single-track () "Toggle if Emms plays a single track and stops." (interactive) (with-current-emms-playlist (cond (emms-single-track (setq emms-single-track nil) (message "single track mode disabled for %s" (buffer-name))) (t (setq emms-single-track t) (message "single track mode enabled for %s" (buffer-name)))))) (defun emms-toggle-random-playlist () "Toggle whether emms plays the tracks randomly or sequentially. See `emms-random-playlist'." (interactive) (setq emms-random-playlist (not emms-random-playlist)) (if emms-random-playlist (progn (setq emms-player-next-function 'emms-random) (message "Will play the tracks randomly.")) (setq emms-player-next-function 'emms-next-noerror) (message "Will play the tracks sequentially."))) (defun emms-toggle-repeat-playlist () "Toggle whether emms repeats the playlist after it is done. See `emms-repeat-playlist'." (interactive) (setq emms-repeat-playlist (not emms-repeat-playlist)) (if emms-repeat-playlist (message "Will repeat the playlist after it is done.") (message "Will stop after the playlist is over."))) (defun emms-toggle-repeat-track () "Toggle whether emms repeats the current track. See `emms-repeat-track'." (interactive) (setq emms-repeat-track (not emms-repeat-track)) (if emms-repeat-track (message "Will repeat the current track.") (message "Will advance to the next track after this one."))) (defun emms-sort-track-name-less-p (a b) "Return non-nil if the track name of A sorts before B." (string< (emms-track-name a) (emms-track-name b))) (defun emms-ensure-player-playing-p () "Raise an error if no player is playing right now." (when (not emms-player-playing-p) (error "No EMMS player playing right now"))) (defun emms-completing-read (&rest args) "Read a string in the minibuffer, with completion. Set `emms-completing-read' to determine which function to use. See `completing-read' for a description of ARGS." (apply emms-completing-read-function args)) (defun emms-display-modes () "Display the current EMMS play modes." (interactive) (with-current-emms-playlist (message "repeat playlist: %s, repeat track: %s, random: %s, single %s" (if emms-repeat-playlist "yes" "no") (if emms-repeat-track "yes" "no") (if emms-random-playlist "yes" "no") (if emms-single-track "yes" "no")))) ;;; Compatibility functions (require 'emms-compat) ;;; Utility functions (defun emms-insert-file-contents (filename &optional visit) "Insert the contents of file FILENAME after point. Do character code conversion and end-of-line conversion, but none of the other unnecessary things like format decoding or `find-file-hook'. If VISIT is non-nil, the buffer's visited filename and last save file modtime are set, and it is marked unmodified. If visiting and the file does not exist, visiting is completed before the error is signaled." (let ((format-alist nil) (after-insert-file-functions nil) (inhibit-file-name-handlers (append '(jka-compr-handler image-file-handler epa-file-handler) inhibit-file-name-handlers)) (inhibit-file-name-operation 'insert-file-contents)) (insert-file-contents filename visit))) ;;; Dictionaries ;; This is a simple helper data structure, used by both players ;; and tracks. (defsubst emms-dictionary (name) "Create a new dictionary of type NAME." (list name)) (defsubst emms-dictionary-type (dict) "Return the type of the dictionary DICT." (car dict)) (defun emms-dictionary-get (dict name &optional default) "Return the value of NAME in DICT." (let ((item (assq name (cdr dict)))) (if item (cdr item) default))) (defun emms-dictionary-set (dict name value) "Set the value of NAME in DICT to VALUE." (let ((item (assq name (cdr dict)))) (if item (setcdr item value) (setcdr dict (append (cdr dict) (list (cons name value)))))) dict) ;;; Tracks ;; This is a simple datatype to store track information. ;; Each track consists of a type (a symbol) and a name (a string). ;; In addition, each track has an associated dictionary of information. (defun emms-track (type name) "Create an EMMS track with type TYPE and name NAME." (let ((track (when emms-cache-get-function (funcall emms-cache-get-function type name)))) (when (not track) (setq track (emms-dictionary '*track*)) ;; Prevent the cache from being called for these two sets (let ((emms-cache-modified-function nil)) (emms-track-set track 'type type) (emms-track-set track 'name name)) (when emms-cache-set-function (funcall emms-cache-set-function type name track))) ;; run any hooks regardless of a cache hit, as the entry may be ;; old (run-hook-with-args 'emms-track-initialize-functions track) track)) (defun emms-track-p (obj) "True if OBJ is an emms track." (and (listp obj) (eq (car obj) '*track*))) (defun emms-track-type (track) "Return the type of TRACK." (emms-track-get track 'type)) (defun emms-track-name (track) "Return the name of TRACK." (emms-track-get track 'name)) (defun emms-track-get (track name &optional default) "Return the value of NAME for TRACK. If there is no value, return DEFAULT (or nil, if not given)." (emms-dictionary-get track name default)) (defun emms-track-set (track name value) "Set the value of NAME for TRACK to VALUE." (emms-dictionary-set track name value) (when emms-cache-modified-function (funcall emms-cache-modified-function track))) (defun emms-track-description (track) "Return a description of TRACK. This function uses the global value for `emms-track-description-function', rather than anything the current mode might have set. Use `emms-track-force-description' instead if you need to insert a description into a playlist buffer." (funcall (default-value 'emms-track-description-function) track)) (defun emms-track-updated (track) "Information in TRACK got updated." (run-hook-with-args 'emms-track-info-filters track) (emms-playlist-track-updated track) (run-hook-with-args 'emms-track-updated-functions track)) (defun emms-track-simple-description (track) "Simple function to give a user-readable description of a track. If it's a file track, just return the file name. Otherwise, return the type and the name with a colon in between. Hex-encoded characters in URLs are replaced by the decoded character." (let ((type (emms-track-type track))) (cond ((eq 'file type) (emms-track-name track)) ((eq 'url type) (emms-format-url-track-name (emms-track-name track))) (t (concat (symbol-name type) ": " (emms-track-name track)))))) (defun emms-format-url-track-name (name) "Format URL track name for better readability." (url-unhex-string name)) (defun emms-track-force-description (track) "Always return text that describes TRACK. This is used when inserting a description into a buffer. The reason for this is that if no text was returned (i.e. the user defined a track function that returned nil or the empty string), a confusing error message would result." (let ((desc (funcall emms-track-description-function track))) (if (and (stringp desc) (not (string= desc ""))) 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 ;; Playlists are stored in buffers. The current playlist buffer is ;; remembered in the `emms-playlist' variable. The buffer consists of ;; any kind of data. Strings of text with a `emms-track' property are ;; the tracks in the buffer. (defvar emms-playlist-buffers nil "The list of EMMS playlist buffers. You should use the `emms-playlist-buffer-list' function to retrieve a current list of EMMS buffers. Never use this variable for that purpose.") (defvar emms-playlist-selected-marker nil "The marker for the currently selected track.") (make-variable-buffer-local 'emms-playlist-selected-marker) (defvar emms-playlist-buffer-p nil "Non-nil if the current buffer is an EMMS playlist.") (make-variable-buffer-local 'emms-playlist-buffer-p) (defun emms-playlist-ensure-playlist-buffer () "Throw an error if we're not in a playlist-buffer." (when (not emms-playlist-buffer-p) (error "Not an EMMS playlist buffer"))) (defun emms-playlist-set-playlist-buffer (&optional buffer) "Set the current playlist buffer." (interactive (list (let* ((buf-list (mapcar #'(lambda (buf) (list (buffer-name buf))) (emms-playlist-buffer-list))) (sorted-buf-list (sort buf-list #'(lambda (lbuf rbuf) (< (length (car lbuf)) (length (car rbuf)))))) (default (or (and emms-playlist-buffer-p ;; default to current buffer (buffer-name)) ;; pick shortest buffer name, since it is ;; likely to be a shared prefix (car sorted-buf-list)))) (emms-completing-read "Playlist buffer to make current: " sorted-buf-list nil t default)))) (let ((buf (if buffer (get-buffer buffer) (current-buffer)))) (with-current-buffer buf (emms-playlist-ensure-playlist-buffer)) (setq emms-playlist-buffer buf) (when (called-interactively-p 'interactive) (message "Set current EMMS playlist buffer")) buf)) (defun emms-playlist-new (&optional name) "Create a new playlist buffer. The buffer is named NAME, but made unique. NAME defaults to `emms-playlist-buffer-name'. If called interactively, the new buffer is also selected." (interactive) (let ((buf (generate-new-buffer (or name emms-playlist-buffer-name)))) (with-current-buffer buf (when (not (eq major-mode emms-playlist-default-major-mode)) (funcall emms-playlist-default-major-mode)) (setq emms-playlist-buffer-p t)) (add-to-list 'emms-playlist-buffers buf) (when (called-interactively-p 'interactive) (switch-to-buffer buf)) buf)) (defun emms-playlist-buffer-list () "Return a list of EMMS playlist buffers. The first element is guaranteed to be the current EMMS playlist buffer, if it exists, otherwise the slot will be used for the other EMMS buffers. The list will be in newest-first order." ;; prune dead buffers (setq emms-playlist-buffers (emms-delete-if (lambda (buf) (not (buffer-live-p buf))) emms-playlist-buffers)) ;; add new buffers (mapc (lambda (buf) (when (buffer-live-p buf) (with-current-buffer buf (when (and emms-playlist-buffer-p (not (memq buf emms-playlist-buffers))) (setq emms-playlist-buffers (cons buf emms-playlist-buffers)))))) (buffer-list)) ;; force current playlist buffer to head position (when (and (buffer-live-p emms-playlist-buffer) (not (eq (car emms-playlist-buffers) emms-playlist-buffer))) (setq emms-playlist-buffers (cons emms-playlist-buffer (delete emms-playlist-buffer emms-playlist-buffers)))) emms-playlist-buffers) (defun emms-playlist-current-kill () "Kill the current EMMS playlist buffer and switch to the next one." (interactive) (when (buffer-live-p emms-playlist-buffer) (let ((new (cadr (emms-playlist-buffer-list)))) (if new (let ((old emms-playlist-buffer)) (setq emms-playlist-buffer new emms-playlist-buffers (cdr emms-playlist-buffers)) (kill-buffer old) (switch-to-buffer emms-playlist-buffer)) (with-current-buffer emms-playlist-buffer (bury-buffer)))))) (defun emms-playlist-current-clear () "Clear the current playlist. If no current playlist exists, a new one is generated." (interactive) (if (or (not emms-playlist-buffer) (not (buffer-live-p emms-playlist-buffer))) (setq emms-playlist-buffer (emms-playlist-new)) (with-current-buffer emms-playlist-buffer (emms-playlist-clear)))) (defun emms-playlist-clear () "Clear the current buffer." (interactive) (emms-playlist-ensure-playlist-buffer) (let ((inhibit-read-only t)) (widen) (delete-region (point-min) (point-max))) (run-hooks 'emms-playlist-cleared-hook)) ;;; Point movement within the playlist buffer. (defun emms-playlist-track-at (&optional pos) "Return the track at POS (point if not given), or nil if none." (emms-playlist-ensure-playlist-buffer) (emms-with-widened-buffer (get-text-property (or pos (point)) 'emms-track))) (defun emms-playlist-next () "Move to the next track in the current buffer." (emms-playlist-ensure-playlist-buffer) (let ((next (next-single-property-change (point) 'emms-track))) (when (not next) (error "No next track")) (when (not (emms-playlist-track-at next)) (setq next (next-single-property-change next 'emms-track))) (when (or (not next) (= next (point-max))) (error "No next track")) (goto-char next))) (defun emms-playlist-previous () "Move to the previous track in the current buffer." (emms-playlist-ensure-playlist-buffer) (let ((prev (previous-single-property-change (point) 'emms-track))) (when (not prev) (error "No previous track")) (when (not (get-text-property prev 'emms-track)) (setq prev (or (previous-single-property-change prev 'emms-track) (point-min)))) (when (or (not prev) (not (get-text-property prev 'emms-track))) (error "No previous track")) (goto-char prev))) (defun emms-playlist-first () "Move to the first track in the current buffer." (emms-playlist-ensure-playlist-buffer) (let ((first (condition-case nil (save-excursion (goto-char (point-min)) (when (not (emms-playlist-track-at (point))) (emms-playlist-next)) (point)) (error nil)))) (if first (goto-char first) (error "No first track")))) (defun emms-playlist-last () "Move to the last track in the current buffer." (emms-playlist-ensure-playlist-buffer) (let ((last (condition-case nil (save-excursion (goto-char (point-max)) (emms-playlist-previous) (point)) (error nil)))) (if last (goto-char last) (error "No last track")))) (defun emms-playlist-delete-track () "Delete the track at point." (emms-playlist-ensure-playlist-buffer) (funcall emms-playlist-delete-track-function)) ;;; Track selection (defun emms-playlist-selected-track () "Return the currently selected track." (emms-playlist-ensure-playlist-buffer) (when emms-playlist-selected-marker (emms-playlist-track-at emms-playlist-selected-marker))) (defun emms-playlist-current-selected-track () "Return the currently selected track in the current playlist." (with-current-emms-playlist (emms-playlist-selected-track))) (defun emms-playlist-selected-track-at-p (&optional point) "Return non-nil if POINT (defaulting to point) is on the selected track." (when emms-playlist-selected-marker (or (= emms-playlist-selected-marker (or point (point))) (let ((p (previous-single-property-change (or point (point)) 'emms-track))) (when p (= emms-playlist-selected-marker p)))))) (defun emms-playlist-select (pos) "Select the track at POS." (emms-playlist-ensure-playlist-buffer) (when (not (emms-playlist-track-at pos)) (error "No track at position %s" pos)) (when (not emms-playlist-selected-marker) (setq emms-playlist-selected-marker (make-marker))) (set-marker-insertion-type emms-playlist-selected-marker t) (set-marker emms-playlist-selected-marker pos) (run-hooks 'emms-playlist-selection-changed-hook)) (defun emms-playlist-select-next () "Select the next track in the current buffer." (emms-playlist-ensure-playlist-buffer) (save-excursion (goto-char (if (and emms-playlist-selected-marker (marker-position emms-playlist-selected-marker)) emms-playlist-selected-marker (point-min))) (condition-case nil (progn (if emms-repeat-playlist (condition-case nil (emms-playlist-next) (error (emms-playlist-first))) (emms-playlist-next)) (emms-playlist-select (point))) (error (error "No next track in playlist"))))) (defun emms-playlist-current-select-next () "Select the next track in the current playlist." (with-current-emms-playlist (emms-playlist-select-next))) (defun emms-playlist-select-previous () "Select the previous track in the current buffer." (emms-playlist-ensure-playlist-buffer) (save-excursion (goto-char (if (and emms-playlist-selected-marker (marker-position emms-playlist-selected-marker)) emms-playlist-selected-marker (point-max))) (condition-case nil (progn (if emms-repeat-playlist (condition-case nil (emms-playlist-previous) (error (emms-playlist-last))) (emms-playlist-previous)) (emms-playlist-select (point))) (error (error "No previous track in playlist"))))) (defun emms-playlist-current-select-previous () "Select the previous track in the current playlist." (with-current-emms-playlist (emms-playlist-select-previous))) (defun emms-playlist-select-random () "Select a random track in the current buffer." (emms-playlist-ensure-playlist-buffer) ;; FIXME: This is rather inefficient. (save-excursion (let ((track-indices nil)) (goto-char (point-min)) (emms-walk-tracks (setq track-indices (cons (point) track-indices))) (setq track-indices (vconcat track-indices)) (emms-playlist-select (aref track-indices (random (length track-indices))))))) (defun emms-playlist-current-select-random () "Select a random track in the current playlist." (with-current-emms-playlist (emms-playlist-select-random))) (defun emms-playlist-select-first () "Select the first track in the current buffer." (emms-playlist-ensure-playlist-buffer) (save-excursion (emms-playlist-first) (emms-playlist-select (point)))) (defun emms-playlist-current-select-first () "Select the first track in the current playlist." (with-current-emms-playlist (emms-playlist-select-first))) (defun emms-playlist-select-last () "Select the last track in the current buffer." (emms-playlist-ensure-playlist-buffer) (save-excursion (emms-playlist-last) (emms-playlist-select (point)))) (defun emms-playlist-current-select-last () "Select the last track in the current playlist." (with-current-emms-playlist (emms-playlist-select-last))) ;;; Playlist manipulation (defun emms-playlist-insert-track (track) "Insert TRACK at the current position into the playlist. This uses `emms-playlist-insert-track-function'." (emms-playlist-ensure-playlist-buffer) (funcall emms-playlist-insert-track-function track)) (defun emms-playlist-update-track () "Update TRACK at point. This uses `emms-playlist-update-track-function'." (emms-playlist-ensure-playlist-buffer) (funcall emms-playlist-update-track-function)) (defun emms-playlist-insert-source (source &rest args) "Insert tracks from SOURCE, supplying ARGS as arguments." (emms-playlist-ensure-playlist-buffer) (save-restriction (narrow-to-region (point) (point)) (apply source args) (run-hooks 'emms-playlist-source-inserted-hook))) (defun emms-playlist-current-insert-source (source &rest args) "Insert tracks from SOURCE in the current playlist. This is supplying ARGS as arguments to the source." (with-current-emms-playlist (apply 'emms-playlist-insert-source source args))) (defun emms-playlist-tracks-in-region (beg end) "Return all tracks between BEG and END." (emms-playlist-ensure-playlist-buffer) (let ((tracks nil)) (save-restriction (narrow-to-region beg end) (goto-char (point-min)) (emms-walk-tracks (setq tracks (cons (emms-playlist-track-at (point)) tracks)))) tracks)) (defun emms-playlist-track-updated (track) "Update TRACK in all playlist buffers." (mapc (lambda (buf) (with-current-buffer buf (when emms-playlist-buffer-p (save-excursion (let ((pos (text-property-any (point-min) (point-max) 'emms-track track))) (while pos (goto-char pos) (emms-playlist-update-track) (setq pos (text-property-any (next-single-property-change (point) 'emms-track) (point-max) 'emms-track track)))))))) (buffer-list)) t) ;;; Simple playlist buffer (defun emms-playlist-simple-insert-track (track) "Insert the description of TRACK at point." (emms-playlist-ensure-playlist-buffer) (let ((inhibit-read-only t)) (insert (emms-propertize (emms-track-force-description track) 'emms-track track) "\n"))) (defun emms-playlist-simple-update-track () "Update the track at point. Since we don't do anything special with the track anyway, just ignore this." nil) (defun emms-playlist-simple-delete-track () "Delete the track at point." (emms-playlist-ensure-playlist-buffer) (when (not (emms-playlist-track-at (point))) (error "No track at point")) (let ((inhibit-read-only t) (region (emms-property-region (point) 'emms-track))) (delete-region (car region) (cdr region)))) (defun emms-playlist-simple-shuffle () "Shuffle the whole playlist buffer." (emms-playlist-ensure-playlist-buffer) (let ((inhibit-read-only t) (current nil)) (widen) (when emms-player-playing-p (setq current (emms-playlist-selected-track)) (goto-char emms-playlist-selected-marker) (emms-playlist-delete-track)) (let* ((tracks (vconcat (emms-playlist-tracks-in-region (point-min) (point-max)))) (len (length tracks)) (i 0)) (delete-region (point-min) (point-max)) (run-hooks 'emms-playlist-cleared-hook) (emms-shuffle-vector tracks) (when current (emms-playlist-insert-track current)) (while (< i len) (emms-playlist-insert-track (aref tracks i)) (setq i (1+ i)))) (emms-playlist-select-first) (goto-char (point-max)))) (defun emms-playlist-simple-sort () "Sort the whole playlist buffer." (emms-playlist-ensure-playlist-buffer) (widen) (let ((inhibit-read-only t) (current (emms-playlist-selected-track)) (tracks (emms-playlist-tracks-in-region (point-min) (point-max)))) (delete-region (point-min) (point-max)) (run-hooks 'emms-playlist-cleared-hook) (mapc 'emms-playlist-insert-track (sort tracks emms-sort-lessp-function)) (let ((pos (text-property-any (point-min) (point-max) 'emms-track current))) (if pos (emms-playlist-select pos) (emms-playlist-first))))) (defun emms-uniq-list (list stringify) "Compare stringfied element of list, and remove duplicate elements." ;; This uses a fast append list, keeping a pointer to the last cons ;; cell of the list (TAIL). It might be worthwhile to provide an ;; abstraction for this eventually. (let* ((hash (make-hash-table :test 'equal)) (result (cons nil nil)) (tail result)) (dolist (element list) (let ((str (funcall stringify element))) (when (not (gethash str hash)) (setcdr tail (cons element nil)) (setq tail (cdr tail))) (puthash str t hash))) (cdr result))) (defun emms-playlist-simple-uniq () "Remove duplicate tracks." ;; TODO: This seems unnecessarily destructive. (emms-playlist-ensure-playlist-buffer) (widen) (let ((inhibit-read-only t) (current (emms-playlist-selected-track)) (tracks (emms-playlist-tracks-in-region (point-min) (point-max)))) (delete-region (point-min) (point-max)) (run-hooks 'emms-playlist-cleared-hook) (mapc 'emms-playlist-insert-track (nreverse (emms-uniq-list tracks 'emms-track-name))) (let ((pos (text-property-any (point-min) (point-max) 'emms-track current))) (if pos (emms-playlist-select pos) (emms-playlist-first))))) (defun emms-default-ok-track-function (track) "A function which OKs all tracks for playing by default." t) ;;; Helper functions (defun emms-property-region (pos prop) "Return a pair of the beginning and end of the property PROP at POS. If POS does not contain PROP, try to find PROP just before POS." (let (begin end) (if (and (> pos (point-min)) (get-text-property (1- pos) prop)) (setq begin (previous-single-property-change (1- pos) prop)) (if (get-text-property pos prop) (setq begin pos) (error "Cannot find the %s property at the given position" prop))) (if (get-text-property pos prop) (setq end (next-single-property-change pos prop)) (if (and (> pos (point-min)) (get-text-property (1- pos) prop)) (setq end pos) (error "Cannot find the %s property at the given position" prop))) (cons (or begin (point-min)) (or end (point-max))))) (defun emms-shuffle-vector (vector) "Shuffle VECTOR." (let ((i (- (length vector) 1))) (while (>= i 0) (let* ((r (random (1+ i))) (old (aref vector r))) (aset vector r (aref vector i)) (aset vector i old)) (setq i (- i 1)))) vector) ;;; Sources ;; A source is just a function which is called in a playlist buffer. ;; It should use `emms-playlist-insert-track' to insert the tracks it ;; knows about. ;; ;; The define-emms-source macro also defines functions ;; emms-play-SOURCE and emms-add-SOURCE. The former will replace the ;; current playlist, while the latter will add to the end. (defmacro define-emms-source (name arglist &rest body) "Define a new EMMS source called NAME. This macro defines three functions: `emms-source-NAME', `emms-play-NAME' and `emms-add-NAME'. BODY should use `emms-playlist-insert-track' to insert all tracks to be played, which is exactly what `emms-source-NAME' will do. The other two functions will be simple wrappers around `emms-source-NAME'; any `interactive' form that you specify in BODY will end up in these. See emms-source-file.el for some examples." (let ((source-name (intern (format "emms-source-%s" name))) (source-play (intern (format "emms-play-%s" name))) (source-add (intern (format "emms-add-%s" name))) (source-insert (intern (format "emms-insert-%s" name))) (docstring "A source of tracks for EMMS.") (interactive nil) (call-args (delete '&rest (delete '&optional arglist)))) (when (stringp (car body)) (setq docstring (car body) body (cdr body))) (when (eq 'interactive (caar body)) (setq interactive (car body) body (cdr body))) `(progn (defun ,source-name ,arglist ,docstring ,@body) (defun ,source-play ,arglist ,docstring ,interactive (if current-prefix-arg (let ((current-prefix-arg nil)) (emms-source-add ',source-name ,@call-args)) (emms-source-play ',source-name ,@call-args))) (defun ,source-add ,arglist ,docstring ,interactive (if current-prefix-arg (let ((current-prefix-arg nil)) (emms-source-play ',source-name ,@call-args)) (emms-source-add ',source-name ,@call-args))) (defun ,source-insert ,arglist ,docstring ,interactive (emms-source-insert ',source-name ,@call-args))))) (defun emms-source-play (source &rest args) "Play the tracks of SOURCE, after first clearing the EMMS playlist." (emms-stop) (emms-playlist-current-clear) (apply 'emms-playlist-current-insert-source source args) (emms-playlist-current-select-first) (emms-start)) (defun emms-source-add (source &rest args) "Add the tracks of SOURCE at the current position in the playlist." (with-current-emms-playlist (save-excursion (goto-char (point-max)) (apply 'emms-playlist-current-insert-source source args)) (when (or (not emms-playlist-selected-marker) (not (marker-position emms-playlist-selected-marker))) (emms-playlist-select-first)))) (defun emms-source-insert (source &rest args) "Insert the tracks from SOURCE in the current buffer." (if (not emms-playlist-buffer-p) (error "Not in an EMMS playlist buffer") (apply 'emms-playlist-insert-source source args))) ;;; User-defined playlists ;;; FIXME: Shuffle is bogus here! (because of narrowing) (defmacro define-emms-combined-source (name shufflep sources) "Define a `emms-play-X' and `emms-add-X' function for SOURCES." `(define-emms-source ,name () "An EMMS source for a tracklist." (interactive) (mapc (lambda (source) (apply (car source) (cdr source))) ,sources) ,(when shufflep '(save-restriction (widen) (emms-shuffle))))) ;;; Players ;; A player is a data structure created by `emms-player'. ;; See the docstring of that function for more information. (defvar emms-player-stopped-p nil "Non-nil if the last EMMS player was stopped by the user.") (defun emms-player (start stop playablep) "Create a new EMMS player. The start function will be START, and the stop function STOP. PLAYABLEP should return non-nil for tracks that this player can play. When trying to play a track, EMMS walks through `emms-player-list'. For each player, it calls the PLAYABLEP function. The player corresponding to the first PLAYABLEP function that returns non-nil is used to play the track. To actually play the track, EMMS calls the START function, passing the chosen track as a parameter. If the user tells EMMS to stop playing, the STOP function is called. Once the player has finished playing, it should call `emms-player-stopped' to let EMMS know." (let ((p (emms-dictionary '*player*))) (emms-player-set p 'start start) (emms-player-set p 'stop stop) (emms-player-set p 'playablep playablep) p)) (defun emms-player-get (player name &optional inexistent) "Return the value of entry NAME in PLAYER." (let ((p (if (symbolp player) (symbol-value player) player))) (emms-dictionary-get p name inexistent))) (defun emms-player-set (player name value) "Set the value of entry NAME in PLAYER to VALUE." (let ((p (if (symbolp player) (symbol-value player) player))) (emms-dictionary-set p name value))) (defun emms-player-for (track) "Return an EMMS player capable of playing TRACK. This will be the first player whose PLAYABLEP function returns non-nil, or nil if no such player exists." (let ((lis emms-player-list)) (while (and lis (not (funcall (emms-player-get (car lis) 'playablep) track))) (setq lis (cdr lis))) (if lis (car lis) nil))) (defun emms-player-start (track) "Start playing TRACK." (if emms-player-playing-p (error "A player is already playing") (let ((player (emms-player-for track))) (if (not player) (error "Don't know how to play track: %S" track) ;; Change default-directory so we don't accidentally block any ;; directories the current buffer was visiting. (let ((default-directory "/")) (funcall (emms-player-get player 'start) track)))))) (defun emms-player-started (player) "Declare that the given EMMS PLAYER has started. This should only be done by the current player itself." (setq emms-player-playing-p player emms-player-paused-p nil) (run-hooks 'emms-player-started-hook)) (defun emms-player-stop () "Stop the current EMMS player." (when emms-player-playing-p (let ((emms-player-stopped-p t)) (funcall (emms-player-get emms-player-playing-p 'stop))) (setq emms-player-playing-p nil))) (defun emms-player-stopped () "Declare that the current EMMS player is finished. This should only be done by the current player itself." (setq emms-player-playing-p nil) (if emms-player-stopped-p (run-hooks 'emms-player-stopped-hook) (sleep-for emms-player-delay) (run-hooks 'emms-player-finished-hook) (funcall emms-player-next-function))) (defun emms-player-pause () "Pause the current EMMS player." (cond ((not emms-player-playing-p) (error "Can't pause player, nothing is playing")) (emms-player-paused-p (let ((resume (emms-player-get emms-player-playing-p 'resume)) (pause (emms-player-get emms-player-playing-p 'pause))) (cond (resume (funcall resume)) (pause (funcall pause)) (t (error "Player does not know how to pause")))) (setq emms-player-paused-p nil) (run-hooks 'emms-player-paused-hook)) (t (let ((pause (emms-player-get emms-player-playing-p 'pause))) (if pause (funcall pause) (error "Player does not know how to pause"))) (setq emms-player-paused-p t) (run-hooks 'emms-player-paused-hook)))) (defun emms-player-seek (seconds) "Seek the current player by SECONDS seconds. This can be a floating point number for fractions of a second, or negative to seek backwards." (if (not emms-player-playing-p) (error "Can't seek player, nothing playing right now") (let ((seek (emms-player-get emms-player-playing-p 'seek))) (if (not seek) (error "Player does not know how to seek") (funcall seek seconds) (run-hook-with-args 'emms-player-seeked-functions seconds))))) (defun emms-player-seek-to (seconds) "Seek the current player to SECONDS seconds. This can be a floating point number for fractions of a second, or negative to seek backwards." (if (not emms-player-playing-p) (error "Can't seek-to player, nothing playing right now") (let ((seek (emms-player-get emms-player-playing-p 'seek-to))) (if (not seek) (error "Player does not know how to seek-to") (funcall seek seconds) (run-hook-with-args 'emms-player-time-set-functions seconds))))) (provide 'emms) ;;; emms.el ends here �����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������emms-6.00/emms.info���������������������������������������������������������������������������������0000664�0001750�0001750�00000505652�13746063641�012443� 0����������������������������������������������������������������������������������������������������ustar �yrk�����������������������������yrk��������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������This is emms.info, produced by makeinfo version 6.1 from emms.texinfo. (C) 2004, 2005, 2006, 2007, 2008, 2009, 2010, 2011, 2014, 2015, 2016 Free Software Foundation, Inc. Permission is granted to copy, distribute and/or modify this document under the terms of the GNU Free Documentation License, Version 1.1 or any later version published by the Free Software Foundation; with no Invariant Sections, no Front-Cover Texts, and no Back-Cover Texts. A copy of the license is included in the section entitled "GNU Free Documentation License". INFO-DIR-SECTION Emacs START-INFO-DIR-ENTRY * Emms: (emms). The Emacs Multimedia System END-INFO-DIR-ENTRY  File: emms.info, Node: Top, Next: Introduction, Prev: (dir), Up: (dir) Emms Manual *********** This is the Manual for the Emacs Multimedia System. (C) 2004, 2005, 2006, 2007, 2008, 2009, 2010, 2011, 2014, 2015, 2016 Free Software Foundation, Inc. Permission is granted to copy, distribute and/or modify this document under the terms of the GNU Free Documentation License, Version 1.1 or any later version published by the Free Software Foundation; with no Invariant Sections, no Front-Cover Texts, and no Back-Cover Texts. A copy of the license is included in the section entitled "GNU Free Documentation License". * Menu: Starting out * Introduction:: Introduction to Emms. * Quickstart Guide:: First steps with Emms for new users. * Installation:: How to install Emms on your System. * Setup:: How to setup Emms. * Configuration:: More detailed setup and configuration. * Getting Help:: Where to get help with Emms and make suggestions. * Formats and Freedom:: File formats without restrictions. Emms basics * Basic Commands:: How to control Emms with ease. * The Core File:: The inner core of Emms. * Sources:: Sources for playlists-creation. * Simple Players:: Some simple players. * Playlists:: How Emms organizes media. Advanced Features * Track Information:: More narrative track descriptions. * Interactive Playlists:: Interactive Playlists. * Markable Playlists:: Allow tracks to be marked. * Extending Emms:: How to define new players and modules. Modules and Extensions * The Browser:: Advanced metadata browsing. * Sorting Playlists:: Sorting the order of the tracks. * Persistent Playlists:: Restoring playlists on emacs startup. * Editing Tracks:: Editing track information from within Emms. * Emms Mode Line:: Emms information on the mode line. * Limiting:: Derive a new playlist from the current. * Music Player Daemon:: Interface to Music Player Daemon. * Lyrics:: Displaying lyrics synchronously. * Volume:: Changing the volume. * 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 * Copying:: The GNU General Public License gives you permission to redistribute Emms on certain terms; it also explains that there is no warranty. * The GNU FDL:: The license for this documentation. Indices * Concept Index:: * Function Index:: * Variable Index:: * Keybinding Index:: -- The Detailed Node Listing -- Here are some other nodes which are really inferiors of the ones already listed, mentioned here so you can get to them in one step: Installation * Compiling Emms:: Compiling Emms into Byte-Code. The Core File * User Variables:: Variables for the user to tweak. * Hooks:: Hooks for important Emms functions. * Core Functions:: Providing the basic functionality of Emms. Track Information * Using tinytag:: Track information via tinytag. * Using exiftool:: Track information via exiftool. * Using TagLib:: TagLib for track information. * Defining Info Methods:: Defining new info methods. Extending Emms * New Player:: How to define a new player. * Simple Player for `play':: Example player using 'play'. * More Complex Player:: Example of a complex player using 'mpg321'.  File: emms.info, Node: Introduction, Next: Quickstart Guide, Up: Top 1 Introduction ************** Emms is the Emacs Multi-Media System. It tries to be a clean and small application to play multimedia files from Emacs using external players. Many of its ideas are derived from MpthreePlayer (http://www.nongnu.org/mp3player), but it tries to be more general and more clean. This manual tries to be the definitive source of information about Emms, an online version of the manual is available at: <http://www.gnu.org/software/emms/manual/>. The basic functionality of Emms consists of three parts: The core, the sources, and the players. The core resides in 'emms.el', and provides a simple playlist and the basic functionality to use all the other features of Emms. It provides the common user commands and interfaces for other parts. It thinks in tracks, where a track is the combination of a type and a name - e.g. the track type 'file has a name that is the file name. Other track types are possible. To get to tracks, the core needs sources. The file 'emms-source-file.el' provides simple sources to interact with the file system. When Emms finally has the sources in the playlist, it needs a player to play them. 'emms-player-simple.el' defines a few useful players, and allows you to define your own in a very simple way. The Emms core comes with many additional features to extend its functionality. The way Emms works is easy to customize with your own code or by using 'M-x customize' or by changing the variables directly.  File: emms.info, Node: Quickstart Guide, Next: Installation, Prev: Introduction, Up: Top 2 Quickstart Guide ****************** This chapter demonstrates how to setup Emms so that you can start listening to your music without having to read all of the documentation first. This is the tl;dr version of the manual. The first thing you have to do is telling Emacs where Emms is located. Let's say you have it in '~/elisp/emms/'. So add this line to your '.emacs': (add-to-list 'load-path "~/elisp/emms/lisp/") More detailed information about installing Emms can be found in the installation chapter, *Note Installation::. You'll then want to load Emms into Emacs. To achieve this you invoke the 'emms-all' setup function by adding the following three lines to your '.emacs'. (require 'emms-setup) (emms-all) (emms-default-players) The function '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, 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, *Note 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 a number of pieces of software and libraries as sources for track info, see *Note Track Information:: for more. 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 '~/Music' or in subdirectories thereof. (setq emms-source-file-default-directory "~/Music/") OK, now we've set up Emms. Reload your '.emacs' or restart Emacs to let the changes have an effect. Now we will add all our music to a playlist by invoking 'M-x emms-add-directory-tree RET ~/Music/ RET'. We do this because then Emms will read the tags of all your music files and caches them (this is also required for the Emms browser, *Note The Browser::.) To switch to the playlist buffer, invoke 'M-x emms-playlist-mode-go' or simply 'M-x emms'. You may see that some tracks are displayed with their file name, but as Emms populates its tag cahe, track by track, the filenames get replaced with the artist and track name of the file's tag. Go ahead and navigate to a track and hit 'RET' on it to start playback. Now you can start exploring Emms. It's probably best to begin with the basic commands (*note Basic Commands::), the interactive playlists (*note Interactive Playlists::), and the browser (*note The Browser::).  File: emms.info, Node: Installation, Next: Setup, Prev: Quickstart Guide, Up: Top 3 Installation ************** You need to put all the .el files of emms in a directory in your load-path. For example, if you put all those files into ~/elisp/emms/, then in your ~/.emacs, you should do: (add-to-list 'load-path "~/elisp/emms/lisp/") * Menu: * Compiling Emms:: Compiling Emms into Byte-Code.  File: emms.info, Node: Compiling Emms, Up: Installation 3.1 Compiling Emms ================== If you are using XEmacs, you will need to edit 'Makefile' as follows before continuing. EMACS=xemacs SITEFLAG=-no-site-file You can byte-compile Emms by first entering the directory containing the Emms source code, followed by invoking: 'make' Which will byte compile Emms. You can then invoke: 'make install' Which will install Emms into your Emacs directories (provided you have the appropriate permissions to do so on your system). Note that Emms is a light-weight and agile program, you can therefore run Emms just fine without byte compiling it.  File: emms.info, Node: Setup, Next: Configuration, Prev: Installation, Up: Top 4 Setup ******* The 'emms-setup' feature is provided by the file 'emms-setup.el'. It is essentially a collection of shortcuts for loading different Emms features quickly, but everything you can do with 'emms-setup' can also be done manually. We use 'emms-setup' by calling one of the setup functions. -- Function: emms-minimalistic An Emms setup script. Playlists and all the basics for playing media, but nothing else. -- Function: emms-all An Emms setup script. Loads all the stable features which come with the Emms distribution. 'emms-setup' also comes with a convenience function to set a default list of media players. -- Function: emms-default-players Set EMMS-PLAYER-LIST to EMMS-SETUP-DEFAULT-PLAYER-LIST. You can of course write your own Emms setup functions like the above by looking at the existing function definitions in 'emms-setup.el'.  File: emms.info, Node: Configuration, Next: Getting Help, Prev: Setup, Up: Top 5 Configuration *************** This chapter discusses the configuration of Emms in more detail. The following code fragment provides a minimal Emms setup without using the layer of 'emms-setup'. It can maybe be used to better understand the internals of Emms. You can see how Emms needs to know about players (these are defined in 'emms-player-simple') and about sources for tracks (trivial file system based sources, such as this 'emms-directory-tree', are defined in 'emms-source-file'). (require 'emms-player-simple) (require 'emms-source-file) (require 'emms-source-playlist) (setq emms-player-list '(emms-player-mpg321 emms-player-ogg123 emms-player-mplayer)) For a discussion on how to define additional players, see *Note Simple Players::. Much of the behaviour of Emms can be changed by setting variables. For example: (setq emms-info-asynchronously nil) (setq emms-playlist-buffer-name "*Music*") The first 'setq' turns off the asynchronous updating of info tags. The second sets the default name of the Emms playlist buffer. Another way to change Emms variables is to use the M-x 'customize' mechanism provided by Emacs. * Menu: * Finding files and speed:: Finding files quickly or portably.  File: emms.info, Node: Finding files and speed, Up: Configuration 5.1 Finding files and speed =========================== Emms needs to traverse directories in order to find playable media. The default method Emms uses to achive this is 'emms-source-file-directory-tree-internal' as defined in 'emms-source-file.el'. The above method is written portably and will always work, but might be too slow if we want to load several hundred tracks (or more). 'emms-source-file.el' defines another method for finding files, 'emms-source-file-directory-tree-find' which uses GNU/find. 'emms-source-file-directory-tree-find' is usually an order of magnitude faster, but of course will not work if you do not have GNU/find installed. The method Emms will use is defined in the customisable variable EMMS-SOURCE-FILE-DIRECTORY-TREE-FUNCTION.  File: emms.info, Node: Getting Help, Next: Formats and Freedom, Prev: Configuration, Up: Top 6 Getting Help ************** If you have a bug to report, need help, or wish to suggest a feature, please feel free to use the Emms mailing list. The address of the list is emms-help@gnu.org. To subscribe to it, visit <http://lists.gnu.org/mailman/listinfo/emms-help>. If you are familiar with the Gmane service, there is a Gmane newsgroup which mirrors this mailing address at gmane.emacs.emms.user. Emms also has a website at <http://www.gnu.org/software/emms/>.  File: emms.info, Node: Formats and Freedom, Next: Basic Commands, Prev: Getting Help, Up: Top 7 Formats and Freedom ********************* Emms is free software, but some of the file formats it can play carry restrictions, they are proprietary file formats. Proprietary software companies are pushing out audio and video formats which restrict when, where and how you can play them, and restrict developers from writing free software which interacts with them. Restrictive file formats put the corporate bottom-line before the public interest. Fortunately there are alternatives like Ogg. Ogg is a professional grade multimedia format. Ogg Vorbis is the compressed audio format (like MP3), and Ogg Theora is the video format. For more information, go to <http://www.xiph.org/>. If you want to transcode audio into a lossless format, you can try FLAC (Free Lossless Audio Codec). FLAC stands out as the fastest and most widely supported lossless audio codec, and the only one that at once is non-proprietary, is unencumbered by patents and has the source code for a reference implementation freely available. For more information about FLAC, go to <http://flac.sourceforge.net/>.  File: emms.info, Node: Basic Commands, Next: The Core File, Prev: Formats and Freedom, Up: Top 8 Basic Commands **************** Before you can use the interface commands, you need a playlist to start with. The following commands allow you to add to the current playlist from different sources: Note that the commands with the "emms-add-" prefix add the source to the playlist but do not start playing it immediately. Conversely, the commands with the "emms-play-" prefix begin playing the track immediately. -- Function: emms-play-file file A source for a single file - either FILE, or queried from the user. If called with a prefix the file will be added like 'emms-add-file'. -- Function: emms-add-file file A source for a single file - either FILE, or queried from the user. If called with a prefix the file will be played like 'emms-play-file'. -- Function: emms-play-directory dir A source for a whole directory tree - either DIR, or queried from the user. -- Function: emms-add-directory dir A source for a whole directory tree - either DIR, or queried from the user. -- Function: emms-play-directory-tree dir A source for multiple directory trees - either DIR, or the value of EMMS-SOURCE-FILE-DEFAULT-DIRECTORY. -- Function: emms-add-directory-tree dir A source for multiple directory trees - either DIR, or the value of EMMS-SOURCE-FILE-DEFAULT-DIRECTORY. -- Function: emms-play-url url A source for an URL - for example, for streaming. -- Function: emms-add-url url A source for an URL - for example, for streaming. -- Function: emms-play-playlist playlist A source for the M3u or PLS playlist format from the file PLAYLIST. -- Function: emms-add-playlist playlist A source for the M3u or PLS playlist format from the file PLAYLIST. -- Function: emms-play-find dir regexp A source that will find files in DIR or EMMS-SOURCE-FILE-DEFAULT-DIRECTORY which match REGEXP. -- Function: emms-add-find dir regexp A source that will find files in DIR or EMMS-SOURCE-FILE-DEFAULT-DIRECTORY which match REGEXP. The basic functionality of Emms is just to play music without being noticed. It provides a few commands to skip the current track and such, but other than that it doesn't show up. Emms provides the following basic user commands (which you might want to bind to keystrokes): -- Function: emms-start Start playing the current playlist -- Function: emms-stop Stop playing -- Function: emms-next Start playing the next track in the playlist -- Function: emms-previous Start playing previous track in the playlist -- Function: emms-shuffle Shuffle the current playlist. This uses EMMS-PLAYLIST-SHUFFLE-FUNCTION. -- Function: emms-sort Sort the current playlist. This uses EMMS-PLAYLIST-SORT-FUNCTION. -- Function: emms-show &optional insertp Describe the current Emms track in the minibuffer. If INSERTP is non-nil, insert the description into the current buffer instead. This function uses EMMS-SHOW-FORMAT to format the current track. The command 'emms-show-all' will pop up a window with the complete information about the track being played. 'emms-show-all' is provided by 'emms-show-all.el', which is included in the 'emms-all' setup level. See *Note Setup::.  File: emms.info, Node: The Core File, Next: Sources, Prev: Basic Commands, Up: Top 9 The Core File *************** The core file 'emms.el' provides the all basic functions for playing music, generating playlists and defining players. * Menu: * User Variables:: Variables for the user to tweak. * Hooks:: Hooks for important Emms functions. * Core Functions:: Providing the basic functionality of Emms.  File: emms.info, Node: User Variables, Next: Hooks, Up: The Core File 9.1 User Variables ================== The core file defines a number of user variables. -- User Option: emms-player-list A list of players Emms can use. You need to set this in order to use Emms to play media. -- User Option: emms-show-format The format to use for 'emms-show'. Any "%s" is replaced by what EMMS-TRACK-DESCRIPTION-FUNCTION returns for the currently playing track. -- User Option: emms-repeat-playlist Non-nil if the Emms playlist should automatically repeat the playlist. If nil, playback will stop when the last track finishes playing. -- User Option: emms-track-description-function Function for describing an Emms track in a user-friendly way. -- User Option: emms-sort-lessp-function A function that compares two tracks, and returns non-nil if the first track should be sorted before the second (see also 'sort').  File: emms.info, Node: Hooks, Next: Core Functions, Prev: User Variables, Up: The Core File 9.2 Hooks ========= The core file provides hook variables for the basic functionality of Emms. -- User Option: emms-player-started-hook A hook run when an Emms player started playing. -- User Option: emms-player-stopped-hook A hook run when an Emms player stopped playing. See also EMMS-PLAYER-FINISHED-HOOK. -- User Option: emms-playlist-source-inserted-hook Hook run when a source got inserted into the playlist. The buffer is narrowed to the new tracks. -- User Option: emms-playlist-selection-changed-hook Hook run after another track is selected in the Emms playlist. -- User Option: emms-playlist-cleared-hook Hook run after the current Emms playlist is cleared. This happens both when the playlist is cleared and when a new buffer is created for it. -- User Option: emms-player-finished-hook Hook run when an Emms player finishes playing a track. Please pay attention to the differences between EMMS-PLAYER-FINISHED-HOOK and EMMS-PLAYER-STOPPED-HOOK. The former is called only when the player is stopped interactively; the latter, only when the player actually finishes playing a track. -- User Option: emms-player-paused-hook Hook run when a player is paused or resumed. Use EMMS-PLAYER-PAUSED-P to find the current state.  File: emms.info, Node: Core Functions, Prev: Hooks, Up: The Core File 9.3 Core Functions ================== The core file also defines all the functions important to the basic use of Emms. There are functions which deal with movement in the playlist. -- Function: emms-next-noerror Start playing the next track in the Emms playlist. Unlike 'emms-next', this function doesn't signal an error when called at the end of the playlist. This function should only be called when no player is playing. This is a good function to put in 'emms-player-finished-hook'. -- Function: emms-playlist-next Move to the previous track in the current buffer. -- Function: emms-playlist-previous Move to the previous track in the current buffer. -- Function: emms-random Jump to a random track. -- Function: emms-toggle-repeat-playlist Toggle whether emms repeats the playlist after it is done. See EMMS-REPEAT-PLAYLIST. -- Function: emms-toggle-repeat-track Toggle whether emms repeats the current track. See EMMS-REPEAT-TRACK. -- Function: emms-toggle-random-playlist Toggle whether emms plays the tracks randomly or sequentially. See EMMS-RANDOM-PLAYLIST. Some functions deal with the getting and setting track information. -- Function: emms-track type name Create a track with type TYPE and name NAME. -- Function: emms-track-type track Return the type of TRACK. -- Function: emms-track-name track Return the name of TRACK. -- Function: emms-track-get name track &optional inexistent Return the value of NAME for TRACK. If there is no value, return DEFAULT (or nil, if not given). -- Function: emms-track-set track name value Set the value of NAME for TRACK to VALUE. -- Function: emms-track-description track Return a description of TRACK. This function uses EMMS-TRACK-DESCRIPTION-FUNCTION. -- Function: emms-player-for track Return an Emms player capable of playing TRACK. This will be the first player whose PLAYABLEP function returns non-nil, or nil if no such player exists. -- Function: emms-playlist-current-selected-track Return the currently selected track in the current playlist. There are also functions which deal with the playing itself. -- Function: emms-player-start track Start playing TRACK. -- Function: emms-player-stop Stop the currently playing player. -- Function: emms-player-stopped Declare that the current Emms player is finished. This should only be done by the current player itself. -- Function: emms-seek seconds Seek the current player SECONDS seconds. This can be a floating point number for sub-second fractions. It can also be negative to seek backwards. -- Function: emms-seek-forward Seek ten seconds forward. -- Function: emms-seek-backward Seek ten seconds backward. For more basic commands defined in the core file see *Note Basic Commands::.  File: emms.info, Node: Sources, Next: Simple Players, Prev: The Core File, Up: Top 10 Sources ********** Sources allow Emms to add and play tracks. Emms comes with a number of sources of its own. Sources are designed so that creating new ones will be easy. For examples of Emms sources for files and directories see 'emms-source-file.el'. -- User Option: emms-source-file-default-directory The default directory to look for media files. -- Function: emms-play-find Play all files in EMMS-SOURCE-FILE-DEFAULT-DIRECTORY that match a specific regular expression. -- Function: emms-source-file &optional file An Emms source for a single file - either FILE, or queried from the user. -- Function: emms-source-files files An Emms source for a list of FILES. -- Function: emms-source-directory &optional dir An Emms source for a whole directory tree - either DIR, or queried from the user -- Function: emms-source-directory-tree & optional dir An Emms source for multiple directory trees - either DIR, or the value of EMMS-SOURCE-FILE-DEFAULT-DIRECTORY. -- Function: emms-source-playlist file An Emms source for playlists. See EMMS-SOURCE-PLAYLIST-FORMATS for a list of supported formats. -- Function: emms-source-playlist-native file An Emms source for a native Emms playlist file. -- Function: emms-source-playlist-m3u file An Emms source for an m3u playlist file. -- Function: emms-source-playlist-pls file An Emms source for a pls playlist file. -- Function: emms-source-find &optional dir regex An Emms source that will find files in DIR or EMMS-SOURCE-FILE-DEFAULT-DIRECTORY that match REGEXP. -- Function: emms-source-file-directory-tree &optional dir Return a list of all files under DIR which match REGEX. -- Function: emms-source-dired Play all marked files of a dired buffer -- Function: emms-source-file-regex Return a regexp that matches everything any player (that supports files) can play. -- Function: emms-locate regexp Search for REGEXP and display the results in a locate buffer  File: emms.info, Node: Simple Players, Next: Playlists, Prev: Sources, Up: Top 11 Simple Players ***************** -- Macro: define-emms-simple-player name types regex command &rest args Define a simple player with the use of 'emms-define-player'. NAME is used to construct the name of the function like emms-player-NAME. TYPES is a list of track types understood by this player. REGEX must be a regexp that matches the filenames the player can play. COMMAND specifies the command line argument to call the player and ARGS are the command line arguments. For a discussion on how to define new players see *Note New Player::. -- Function: emms-player-simple-stop Stop the currently playing process, if indeed there is one. -- Function: emms-player-simple-start filename cmdname params Starts a process playing FILENAME using the specified CMDNAME with the specified PARAMS. -- Function: emms-player-simple-sentinel proc str Sentinel for determining the end of process for the process PROC and the sentinel string STR.  File: emms.info, Node: Playlists, Next: Track Information, Prev: Simple Players, Up: Top 12 Playlists ************ Emms uses Emacs buffers to store the media tracks for playing. We call one such buffer a "playlist buffer" or an "Emms playlist buffer". Emms then proceeds to play the media tracks in the buffer from top to bottom until the end of the playlist. The name of the playlist buffer is defined in the variable EMMS-PLAYLIST-BUFFER-NAME and is set to be an invisible Emacs buffer by default. You can change to any name you want. For an example configuration see *Note Configuration::. You can create any number of playlist buffers you wish. At any time Emms has a single "current" buffer through which it proceeds track by track. -- Function: emms-playlist-new &optional name Create a new playlist buffer. The buffer is named NAME, but made unique. NAME defaults to 'emms-playlist-buffer-name'. If called interactively, the new buffer is also selected. -- Function: emms-playlist-save &optional format file Store the current playlist to FILE as the type FORMAT. The default format is specified by EMMS-SOURCE-PLAYLIST-DEFAULT-FORMAT. The current Emms playlist buffer is stored in the variable EMMS-PLAYLIST-BUFFER.  File: emms.info, Node: Track Information, Next: Interactive Playlists, Prev: Playlists, Up: Top 13 Track Information ******************** Without a way to read the embedded track information inside files, Emms will only be able to list file names and file locations. Therefore Emms is distributed with support for a number of pieces of software and libraries which can be used to provide access to track metadata such as the artist's name, track name, album title, etc. Emms can use a number of different ways to populate the playlist with track information. These methods require the installation some additional software, free software of course, that Emms can then call to read the metadata from the files. * Tinytag, a small python utility. See *Note Using tinytag::. * Exiftool, written in perl. See *Note Using exiftool::. * The TagLib library can be used by compiling a small piece of "shim" software. See *Note Using TagLib::. You can also use a combination of format-specific tools if needed, such as 'emms-info-mp3info.el', 'emms-info-ogginfo.el', 'emms-info-opusinfo.el', and 'emms-cue.el'. These three packages are front-ends for command-line tools. Ogg track information is retrieved using the ogginfo (http://directory.fsf.org/audio/ogg/vorbistools.html) and the <https://www.opus-codec.org/ opusinfo> software. Likewise, mp3 track information is available using mp3info (http://www.ibiblio.org/mp3info/). 'emms-cue.el' retrieves tracks information for ape/flac files by parsing a cue sheet file, which is plain text. Automatic track information retrieval is enabled by default in the 'emms-all' setup level provided by 'emms-setup.el'. For more information about 'emms-setup.el' see *Note Setup::. If you would like to know how Emms track retreival works and how we can define new methods for track retrieval see *Note Defining Info Methods::. There are a number of user variables which control the behaviour of 'emms-info'. -- User Option: emms-info-auto-update Non-nil when Emms should update track information if the file changes. This will cause hard drive activity on track loading. If this is too annoying for you, set this variable to nil. -- User Option: emms-info-asynchronously Non-nil when track information should be loaded asynchronously. This requires the feature 'later-do' which is provided by the file 'later-do.el', which comes with Emms. See LATER-DO-BATCH for performance tweaking. -- User Option: emms-info-functions Functions which add information to tracks. Each is called with a track as argument. * Menu: * Using tinytag:: Track information via tinytag. * Using exiftool:: Track information via exiftool. * Using TagLib:: TagLib for track information. * Defining Info Methods:: Defining new info methods.  File: emms.info, Node: Using tinytag, Next: Using exiftool, Up: Track Information 13.1 Using tinytag ================== Make sure that the python program tinytag is installed on your system. It is available at tinytag (https://pypi.org/project/tinytag/). Configure tinytag as the sole info method (competing and overlapping methods can cause confusion) for Emms: (setq emms-info-functions '(emms-info-tinytag))  File: emms.info, Node: Using exiftool, Next: Using TagLib, Prev: Using tinytag, Up: Track Information 13.2 Using exiftool =================== Make sure that the perl program exiftool is installed on your system. It is available at <https://exiftool.org/>. Then set exiftool as the sole info method with: (setq emms-info-functions '(emms-info-exiftool))  File: emms.info, Node: Using TagLib, Next: Defining Info Methods, Prev: Using exiftool, Up: Track Information 13.3 Using TagLib ================= 'emms-info-libtag.el' uses a tiny C shim (included in the src/ directory) program to take advantage of TagLib (http://taglib.github.io/). The communication with the TagLib library is done via a tiny program written in C++ 'emms-print-metadata.cpp', which comes with Emms. To compile 'emms-print-metadata' invoke: 'make emms-print-metadata' The resultant binary will be installed when you invoke: 'make install' as in *Note Compiling Emms::. It is of course also possible to install only the 'emms-print-metadata' binary where your system can find and execute it without installing all of Emms via the make command. Once the binary is available load 'emms-info-libtag' and make it the _only_ info function with (note that if you have caching enabled you may have to delete the existing cache and repopulate it in order to see the TagLib data): (require 'emms-info-libtag) (setq emms-info-functions '(emms-info-libtag))  File: emms.info, Node: Defining Info Methods, Prev: Using TagLib, Up: Track Information 13.4 Defining Info Methods ========================== An info method essentially consists of a function which given an Emms track returns the appropriate info for that track. We can for example look at the predefined method for retrieving information about audio tracks in the Ogg format. The function 'emms-info-ogginfo' provided by 'emms-info-ogginfo.el' accepts an Emms track as a single argument and returns the appropriate information string. We then register our info function with Emms by adding it to the EMMS-INFO-FUNCTIONS list. The function will then be called at the right time to provide track info. (add-to-list 'emms-info-functions 'emms-info-ogginfo)  File: emms.info, Node: Interactive Playlists, Next: Markable Playlists, Prev: Track Information, Up: Top 14 Interactive Playlists ************************ Emms provides a visual, interactive playlist mode as well as the ability to use playlists without ever looking at then. This visual, interactive mode is called the 'emms-playlist-mode' and is defined in 'emms-playlist-mode.el'. The interactive playlist mode is enabled by default in the 'emms-all' setup level. For more information about Emms setup levels see *Note Setup::. -- Function: emms-playlist-mode-go Switch to the current emms-playlist buffer and use emms-playlist-mode. If you wish to make this the default Emms playlist mode, add the following to your '.emacs'. (setq emms-playlist-default-major-mode 'emms-playlist-mode) The interactive playlist buffer shows the tracks in the current Emms playlist in the order in which they will be played. The current track will be highlighted. When in the interactive playlist mode we can perform different actions on the current playlist. 'a' Add files in the playlist at point to the current playlist buffer. If we are in the current playlist, make a new playlist buffer and set it as current. 'b' Set the current playlist buffer. 'n' Start playing the next track in the playlist. 'p' Start playing the previous track in the playlist. 's' Stop playing. 'P' Pause. '>' Seek ten seconds forward. '<' Seek ten seconds backward. 'f' Describe the currently playing track in the minibuffer. 'c' Display the current track in the center of the screen. 'RET' Start playing the track under point. Note that this is also available with '<mouse-2>'. 'SPC' Scroll up a near full page. 'M-<' Go to the first track in the playlist. 'M->' Go to the last track in the playlist. 'r' Go to a randomly selected track in the playlist. 'q' Put the interactive playlist buffer at the end of the list of all buffers. 'C-x C-s' Save the current playlist buffer to a file. By default, Emms will ask you for confirmation before overwriting an existing playlist. You can silently overwrite existing playlist by setting EMMS-SOURCE-PLAYLIST-ASK-BEFORE-OVERWRITE to nil. '?' Describe the mode. We can also edit the playlist using familiar GNU/Emacs commands: 'C-k' Remove the track under point from the playlist buffer. Also available using the 'd' key. 'C-y' See the command 'yank' 'C-w' See the command 'kill-region' 'M-y' See the command 'yank-pop'. 'C-j' Insert a newline at point. We can use the regular GNU/Emacs killing and yanking commands to move and copy tracks in between playlist buffers. We can use the same commands to insert arbitrary text into the playlist buffers together with the playlist tracks. Text which is not a track is ignored by the program and can therefore be used to include titles and annotations within the playlist.  File: emms.info, Node: Markable Playlists, Next: Extending Emms, Prev: Interactive Playlists, Up: Top 15 Markable Playlists ********************* The Markable Playlists provided by the file 'emms-mark.el' are an alternative to the default interactive playlists, *Note Interactive Playlists::. They allow marking tracks with keybindings familiar to users of dired. To enable the Markable Playlists you have to add (require 'emms-mark) to your '.emacs'. Then you can activate 'emms-mark-mode' by executing 'M-x emms-mark-mode' in a playlist buffer. You can return to the default interactive playlist mode with 'M-x emms-mark-mode-disable'. If you wish to make this the default Emms playlist mode, add the following to your '.emacs'. (setq emms-playlist-default-major-mode 'emms-mark-mode) 'm' Marks the current track and sets point one line forward. If a prefix argument ARG is given, it will mark the next ARG tracks and set point accordingly. A negative argument marks backward. 'U' Unmarks all tracks in the playlist. 't' Toggles mark on the current track. 'u' Unmarks same way as 'emms-mark-forward' marks. '% m' Marks all tracks in the playlist matching the given regular expression. A prefix argument means to unmark them instead. When tracks are marked you can operate on them: 'D' Deletes the marked tracks from the playlist. 'K' Deletes the marked tracks from the playlist and places them in the kill-ring, so that you can 'yank' in into another playlist. 'W' Adds the marked tracks to the kill-ring, so that you can 'yank' them into another playlist. emms-mark is also intent to provide a way for user to select tracks for other command to operate on them. Currently, 'emms-tag-editor.el' uses the emms-mark to edit the tags of selected tracks. Two functions are useful for the elisp programer to handle marked tracks. -- Function: emms-mark-do-with-marked-track This function take a function to perform on all marked tracks. A optional argument 'move-flag' to tell the function to move forward line after calling given function. If the given function didn't change position, the second argument should set to non-nil. -- Function: emms-mark-mapcar-marked-track This function is very similar to 'emms-mark-do-with-marked-track' except it collects result of given function (that's why named with 'mapcar').  File: emms.info, Node: Extending Emms, Next: The Browser, Prev: Markable Playlists, Up: Top 16 Extending Emms ***************** Emms introduces a high abstraction layer for playing music so you can customise it to your needs. * Menu: * New Player:: How to define a new player. * Simple Player for `play':: An example player using 'play'. * More Complex Player:: Example of a complex player using 'mpg321'.  File: emms.info, Node: New Player, Next: Simple Player for `play', Up: Extending Emms 16.1 New Player =============== The file 'emms-player-simple.el' defines some easy players to start with, but it shouldn't be hard to provide a function for your favourite player. We will start with an easy example that shows how we can use the 'play' command under Unix to play our WAV files.  File: emms.info, Node: Simple Player for `play', Next: More Complex Player, Prev: New Player, Up: Extending Emms 16.2 Simple Player for 'play' ============================= Play is a very easy command line player for various format. If you want your emms to play WAV files just put the following lines in you '.emacs': (require 'emms-player-simple) (define-emms-simple-player play '(file) "\\.wav$" "play") Huh! Wasn't that easy? The macro function 'define-emms-simple-player' takes a minimum of three arguments. The first argument (_play_ in our example) defines the name of the player. It's used to name the player functions. The second is a regexp, that defines which files to play with our player. _\\.wav$_ matches any filename ending with a dot and the string wav. The last argument is the actual command line command we use to play our files. You can also add the path but we just assume that the command is in your path. All arguments you add to these three are optional. They define the command line arguments you want to add to your argument. If you want to hear the wav file of your favourite artist in the most possible volume use the following line: (require 'emms-player-simple) (define-emms-simple-player play '(file) "\\artist-*.wav$" "play" "--volume=100") Please notice that you have to add the arguments as strings! The command line tool you use for 'define-emms-simple-player' has to take one song as argument and stop after playing that particular song. For any other concept you will need to customise emms a bit more...  File: emms.info, Node: More Complex Player, Prev: Simple Player for `play', Up: Extending Emms 16.3 More Complex Player ======================== The most players you use will be simple players so you don't need to read this chapter. But if you are curious how you can use (almost) every player in emms read further... In this chapter we will use mpg321 to construct a player that actually can pause a track, restart it and show rest time. We won't implement all of that, but after that chapter you will know how to define it. The command 'define-emms-simple-player' is just a abstraction layer for 'define-emms-player', which is a little bit more complicated but much more powerful! (define-emms-player "emms-mpg321-remote" :start 'emms-mpg321-remote-start :stop 'emms-mpg321-remote-stop :playablep 'emms-mpg321-remote-playable-p) So, that is almost all! 'define-emms-player' takes a minimum of three arguments. The first is the name of the player. The rest are methods with functions to call. Three methods are required: start, stop and playable. Start says Emms how to start a track (sic!), stop how to stop a player and playablep should return non-nil if the player can play the track. So we just need these three functions to get our mpg321-remote: First we code the start function. We will check if there's a open process and start one otherwise. Then we send a string to the process with the filename and set a filter. (defun emms-mpg321-remote-start () (unless (get-process ``mpg321-remote'') (setq emms-mpg321-remote-process (start-process "mpg321-remote-process" "*mpg321*" "mpg321" "-R" "abc")) (process-send-string "mpg321-remote-process" (concat "l " (emms-track-name track))) (set-process-filter emms-mpg321-remote-process 'emms-mpg321-remote-filter))) We need the filter, as mpg321-remote won't quit after playing the track as the simple player do. We wait until the process sends the output "(at-sign)P 0" (the signal of mpg321 that the song ended) to the filter and call emms-mpg321-remote-stop. (defun emms-mpg321-remote-filter (process output) (when (string-match "(at-sign)P 0" output) (emms-mpg321-remote-stop))) 'emms-mpg321-remote-stop' won't do anything interesting. It just test if there are other files to play and close the process otherwise. (defun emms-mpg321-remote-stop () (unless emms-playlist (process-send-string "mpg321-remote-process" "Q\n")) And to make that a playable example I also added 'emms-mpg321-remote-playablep', which I really just steal from 'emms-player-simple.el' (defun emms-mpg321-remote-playablep (track) "Return non-nil when we can play this track." (and (eq 'file (emms-track-type track)) Now we have a ready player and we could add commands like 'emms-mpg321-remote-pause' for example.  File: emms.info, Node: The Browser, Next: Sorting Playlists, Prev: Extending Emms, Up: Top 17 The Browser ************** The Browser allows you to browse the metadata cache and add tracks to your playlist. It includes a powerful interactive mode. The Browser is defined in 'emms-browser.el' and is included in the 'emms-all' setup level. For more information about Emms setup levels see *Note Setup::. You can also manually add the Browser to your Emms setup by loading it explicitly with: (require 'emms-browser) To be properly useful, you should do M-x 'emms-add-directory-tree' to all the files you own at least once so that the cache is fully populated. * Menu: * Browser Interface:: The interactive browser interface. * Filtering Tracks:: Displaying a subset of the tracks. * Displaying Covers:: Displaying album covers in the browser interface. * Changing Looks:: Changing the tree structure, display format and faces.  File: emms.info, Node: Browser Interface, Next: Filtering Tracks, Up: The Browser 17.1 Browser Interface ====================== The browser interface allows you to display and interact with your tracks in many different ways. There are a number of ways to start the browser. -- Function: emms-smart-browse 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. -- Function: emms-browse-by-artist Display the browser and order the tracks by artist. -- Function: emms-browse-by-album Display the browser and order the tracks by album. -- Function: emms-browse-by-genre Display the browser and order the tracks by genre. -- Function: emms-browse-by-year Display the browser and order the tracks by year. Once the Browser is displayed you can use it to managed your track collection and playlists. The Browser is interactive and has its own keybindings. 'C-j' Add all tracks at point, and play the first added track. 'RET' Add all tracks at point. 'SPC' Show or hide (kill) subitems under the current line. '1' Collapse everything. '2' Expand all top level items one level. '3' Expand all top level items two levels. '4' Expand all top level items three levels. 'C' Clear the playlist. 'E' Expand everything. 'd' View the current directory in dired. 'q' Bury the browser buffer. 'r' Jump to a random track. '/' Isearch through the buffer. '<' Redisplay with the previous filter. '>' Redisplay with the next filter. '?' See the Emacs documentation for the function. 'C-/' Undo the previous playlist action. '<C-return>' Add all tracks at point, and play the first added track. '<backtab>' Jump to the previous non-track element. '<tab>' Jump to the next non-track element. 's A' Search the collection by album. 's a' Search the collection by artist. 's s' Search the collection by names. 's t' Search the collection by title. 'b 1' Browse the collection by artist. 'b 2' Browse the collection by album. 'b 3' Browse the collection by genre. 'b 4' Browse the collection by year. 'W a p' Lookup the album using Pitchfork. 'W a w' Lookup the album using Wikipedia.  File: emms.info, Node: Filtering Tracks, Next: Displaying Covers, Prev: Browser Interface, Up: The Browser 17.2 Filtering Tracks ===================== If you want to display a subset of your collection (such as a directory of 80s music, only avi files, etc.) then you can extend the Browser by defining "filters". Show everything: (emms-browser-make-filter "all" 'ignore) Set "all" as the default filter: (emms-browser-set-filter (assoc "all" emms-browser-filters)) Show all files (no streamlists, etc): (emms-browser-make-filter "all-files" (emms-browser-filter-only-type 'file)) Show only tracks in one folder: (emms-browser-make-filter "80s" (emms-browser-filter-only-dir "~/Mp3s/80s")) Show all tracks played in the last month: (emms-browser-make-filter "last-month" (emms-browser-filter-only-recent 30)) After executing the above commands, you can use M-x emms-browser-show-all, emms-browser-show-80s, etc to toggle between different collections. Alternatively you can use '<' and '>' to cycle through the available filters. The second argument to make-filter is a function which returns t if a single track should be filtered. You can write your own filter functions to check the type of a file, etc. Show only tracks not played in the last year: (emms-browser-make-filter "not-played" (lambda (track) (not (funcall (emms-browser-filter-only-recent 365) track)))) Show all files that are not in the pending directory: (emms-browser-make-filter "all" (lambda (track) (or (funcall (emms-browser-filter-only-type 'file) track) (not (funcall (emms-browser-filter-only-dir "~/Media/pending") track)))))  File: emms.info, Node: Displaying Covers, Next: Changing Looks, Prev: Filtering Tracks, Up: The Browser 17.3 Displaying Covers ====================== The browser will attempt to display cover images if they're available. Customize EMMS-BROWSER-COVERS to configure how EMMS should retrieve the covers. By default it looks for images 'cover_small.jpg', '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 EMMS-BROWSER-COVERS to 'emms-browser-cache-thumbnail': covers matching 'emms-browser-thumbnail-filter' will be automatically resized if necessary and cached to EMMS-BROWSER-THUMBNAIL-DIRECTORY. The cache gets automatically updated upon change in the source folder. Customize EMMS-BROWSER-COVERS-FILE-EXTENSIONS to include or exclude specific extensions. 'emms-browser-cache-thumbnail' might be everytime a cover is queried, so to help with performance you can also set EMMS-BROWSER-COVERS to 'emms-browser-cache-thumbnail-async'. The latter is like the former except that it caches queries: every subsequent query will be much faster. The drawback is that it won't see changes made to covers after the first query. To force-refresh the thumbnail cache, you can run 'emms-browser-clear-cache-hash'. Also, Emacs by default will jump around a lot when scrolling a buffer with images. In order to prevent that, you can set SCROLL-UP-AGGRESSIVELY and SCROLL-DOWN-AGGRESSIVELY to the number "0.0". To show a 'no cover' image for albums which don't have a cover, add the following code to your .emacs: (setq emms-browser-default-covers (list "/path/to/cover_small.jpg" nil nil) The medium and large images can be set as well. You can download an example 'no cover' image (http://repose.cx/cover_small.jpg).  File: emms.info, Node: Changing Looks, Prev: Displaying Covers, Up: The Browser 17.4 Changing Looks =================== The Browser's look can be customised. You can change the way the tree structure looks, the display format and display faces. Changing Tree Structure ----------------------- You can change the way the tree is displayed by modifying the function 'emms-browser-next-mapping-type'. The following code displays artist->track instead of artist->album->track when you switch to the 'singles' filter: (defadvice emms-browser-next-mapping-type (after no-album (current-mapping)) (when (eq ad-return-value 'info-album) (setq ad-return-value 'info-title))) (defun toggle-album-display () (if (string= emms-browser-current-filter-name "singles") (ad-activate 'emms-browser-next-mapping-type) (ad-deactivate 'emms-browser-next-mapping-type))) (add-hook 'emms-browser-filter-changed-hook 'toggle-album-display) Furthermore, you can customize EMMS-BROWSER-GET-TRACK-FIELD-FUNCTION to choose which the metadata fields used for the different tree nodes (''info-artist', 'info-year', etc.). For instance, you can choose whether to organize the tree by artist, album artist or performer. Changing Display Format ----------------------- Format strings govern the way items are displayed in the browser and playlist. You can customize these if you wish. EMMS-BROWSER-DEFAULT-FORMAT controls the format to use when no other format has been explicitly defined. By default, only track and albums deviate from the default. To customise the format of a particular type, find the name of the field you want to use (eg 'info-artist', 'info-title', etc), and insert that into emms-browser-<type>-format or emms-browser-playlist-<type>-format. For example, if you wanted to remove track numbers from tracks in both the browser and playlist, you could do: (defvar emms-browser-info-title-format "%i%n") (defvar emms-browser-playlist-info-title-format emms-browser-info-title-format) The format specifiers available include: %i indent relative to the current level %n the value of the item - eg -info-artist might be "pink floyd" %y the album year %A the album name %a the artist name of the track %t the title of the track %T the track number %cS a small album cover %cM a medium album cover %cL a big album cover Note that if you use track-related items like %t, it will take the data from the first track. Changing Display Faces ---------------------- The faces used to display the various fields are also customizable. They are in the format emms-browser-<type>-face, where type is one of "year/genre", "artist", "album" or "track". Note that faces lack the initial "info-" part. For example, to change the artist face, type M-x 'customize-face' 'emms-browser-artist-face'.  File: emms.info, Node: Sorting Playlists, Next: Persistent Playlists, Prev: The Browser, Up: Top 18 Sorting Playlists ******************** The 'emms-playlist-sort' module, defined in the 'emms-playlist-sort.el' package provides functions for sorting Emms playlists, as well as keyboard shortcuts for invoking the functions in the playlist buffer. Most of the functions will sort in reverse order if the command is preceded by a prefix. 'emms-playlist-sort' can be loaded by invoking: (require 'emms-playlist-sort) -- Function: emms-playlist-sort-by-info-artist Sort by artist name. -- Function: emms-playlist-sort-by-play-count Sort by number of times the track has been played. -- Function: emms-playlist-sort-by-info-album Sort by album name. -- Function: emms-playlist-sort-by-last-played Sort by time the track was played last. -- Function: emms-playlist-sort-by-info-title Sort by track title. -- Function: emms-playlist-sort-by-file-extension Sort by filename extension. -- Function: emms-playlist-sort-by-info-performer Sort by performer name. -- Function: emms-playlist-sort-by-info-year Sort by year. -- Function: emms-playlist-sort-by-info-note Sort by track notes. -- Function: emms-playlist-sort-by-info-composer Sort by composer. -- Function: emms-playlist-sort-by-name Sort by track name. -- Function: emms-playlist-sort-by-file-mtime Sort by file mtime.  File: emms.info, Node: Persistent Playlists, Next: Editing Tracks, Prev: Sorting Playlists, Up: Top 19 Persistent Playlists *********************** The Emms module 'emms-history.el' makes playlists persistent over emacs sessions. To make use of this feature put this into your ~/.emacs. (require 'emms-history) When you kill emacs all playlists will be saved in the file given by the variable: -- User Option: emms-history-file The file to save playlists in. It defaults to "~/.emacs.d/emms-history". After you started up emacs again, you can restore all saved playlists with this function. -- Function: emms-history-load Restore all playlists in 'emms-history-file'. If that should be done automatically on each startup, put these lines into your ~/.emacs. (require 'emms-history) (emms-history-load) Normally 'emms-history' only restores playlists. If you want it to start playback afterwards, you can tweak this variable. -- User Option: emms-history-start-playing If non-nil emms starts playing the current track after 'emms-history-load' was invoked. The default value is nil.  File: emms.info, Node: Editing Tracks, Next: Emms Mode Line, Prev: Persistent Playlists, Up: Top 20 Editing Tracks ***************** Using '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 'mid3v2' and 'vorbiscomment'. Use the keybinding 'E' to edit the tags of track under point in the playlist or all marked tracks (*note Markable Playlists:: for how to mark tracks). The track's tag informations are listed in a special buffer '*Emms-TAGS*' in text format. Field names are marked in bold face and are not editable. Any tag information is placed behind an equal sign and is changable. A special field 'name' is the track's file name. If any change is made in this field, the track's file will be renamed to the new name. When you finished editing the tag infos use 'C-c C-c' (which calls 'emms-tag-editor-submit-and-exit') to submit the changes and close the '*Emms-TAGS*' buffer. There are a few commands to perform changes on all tracks. -- Function: emms-tag-editor-set-all tag value Set TAG to VALUE in all tracks. If transient-mark-mode is turned on, you can apply the command to a selected region. If 'transient-mark-mode' is on and the mark is active, the changes will only take effect on the tracks in the region. -- Function: emms-tag-editor-replace-in-tag tag from to Query and replace text in selected TAG. For example, if the info-title tag is selected, then only perform replacement in title tags. If 'transient-mark-mode' is on and the mark is active, the changes will only take effect on the tracks in the region. -- Function: emms-tag-editor-transpose-tag tag1 tag2 Transpose value of TAG1 and TAG2. If 'transient-mark-mode' is on and the mark is active, the changes will only take effect on the tracks in the region. -- Function: emms-tag-editor-submit arg Make modified tags take affect. With prefix argument, bury the tag edit buffer. If you want to extend the tag editor to work with file formats other than 'mp3' and 'ogg', have a look at these variables. -- Variable: emms-tag-editor-formats This variable determine how to insert track fields to 'emms-tag-editor-edit-buffer'. Emms tag info editable fields is usually determined by the extension of track name. The variable 'emms-tag-editor-tags' contains all tags that emms track may have. A single charactar is assigned to the tag to make the 'emms-tag-editor-formats' easier to generate. -- Variable: emms-tag-editor-tagfile-functions To write tags to track file, an extern program should specified in this variable. Renaming Files ============== The tag editor is also capable to rename the file of the track at point or all files of the marked tracks according to the value this variable. -- User Option: emms-tag-editor-rename-format When 'emms-tag-editor-rename' is invoked the track's file will be renamed according this format specification. The file extension will be added automatically. It uses the format specs defined in 'emms-tag-editor-tags'. The default value is "%a - %l - %n - %t", so that files are named <Artist> - <Album> - <Tracknumber> - <Title>.<extension> after renaming. To perform the renaming put point on the track you want to rename or mark some tracks. Then hit 'R' which calls this function: -- Function: emms-tag-editor-rename Rename the file corresponding to track at point or all marked tracks according to the value of 'emms-tag-editor-rename-format'.  File: emms.info, Node: Emms Mode Line, Next: Limiting, Prev: Editing Tracks, Up: Top 21 Emms Mode Line ***************** We can display information about the currenty playing track on the Emacs mode line using the package 'emms-mode-line' which is provided by the file 'emms-mode-line.el'. To activate this feature invoke: (require 'emms-mode-line) (emms-mode-line 1) It is also possible to display the amount of time a track has been playing. This feature is defined in the 'emms-playing-time' package which is provided by the file 'emms-playing-time.el'. To use this feature invoke: (require 'emms-playing-time) (emms-playing-time 1) Note: '(emms-playing-time -1)' will disable emms-playing-time module completely, and is not recommended. (since some other emms modules may rely on it) Instead, to toggle displaying playing time on mode line, one could call 'emms-playing-time-enable-display' and 'emms-playing-time-disable-display'." -- Function: emms-playing-time-enable-display Display playing time on mode line. -- Function: emms-playing-time-disable-display Remove playing time from mode line.  File: emms.info, Node: Limiting, Next: Music Player Daemon, Prev: Emms Mode Line, Up: Top 22 Limiting *********** The package 'emms-playlist-limit', provided by 'emms-playlist-limit.el', allows creating a new playlist derived from the playlist in the current buffer. For instance, it is possible to create a new playlist containing only a certain artist or genre from the playlist in the current buffer. If the playlist in the current buffer is the emms current playlist then the derived playlist becomes current. '/ a' Create a new playlist buffer and populate it with tracks whose artist info field matches the given regular expression (default: the artist info field of the track at point). '/ b' Create a new playlist buffer and populate it with tracks whose album info field matches the given regular expression (default: the album info field of the track at point). '/ c' Create a new playlist buffer and populate it with tracks whose composer info field matches the given regular expression (default: the composer info field of the track at point). '/ d' Create a new playlist buffer and populate it with tracks whose track description matches the given regular expression (default: the track description of the track at point). '/ g' Create a new playlist buffer and populate it with tracks whose genre info field matches the given regular expression (default: the genre info field of the track at point). '/ n' Create a new playlist buffer and populate it with tracks whose name matches the given regular expression (default: the name of the track at point). '/ p' Create a new playlist buffer and populate it with tracks whose performer info field matches the given regular expression (default: the performer info field of the track at point). '/ t' Create a new playlist buffer and populate it with tracks whose title info field matches the given regular expression (default: the title info field of the track at point). '/ y' Create a new playlist buffer and populate it with tracks whose year info field matches the given regular expression (default: the year info field of the track at point). '/ /' Switch to the original playlist buffer (if it still exists).  File: emms.info, Node: Music Player Daemon, Next: Lyrics, Prev: Limiting, Up: Top 23 Music Player Daemon ********************** Emms provides an interface to the Music Player Daemon (http://www.musicpd.org/)(MusicPD) software. The package is called 'emms-player-mpd' and is provided by the file 'emms-player-mpd.el'. The advantages of using MusicPD as an Emms backend include the following. * minimal CPU usage * fast access of track information * optional crossfade Setup ----- To load 'emms-player-mpd' invoke: (require 'emms-player-mpd) Set the variables EMMS-PLAYER-MPD-SERVER-NAME and EMMS-PLAYER-MPD-SERVER-PORT to the location and port (respectively) of your MusicPD server. For example: (setq emms-player-mpd-server-name "localhost") (setq emms-player-mpd-server-port "6600") If your MusicPD setup requires a password, you will to set EMMS-PLAYER-MPD-SERVER-PASSWORD as follows. (setq emms-player-mpd-server-password "mypassword") To get track information from MusicPD, invoke the following: (add-to-list 'emms-info-functions 'emms-info-mpd) Adding 'emms-player-mpd' to your Emms player list is accomplished by invoking: (add-to-list 'emms-player-list 'emms-player-mpd) Unless your MusicPD is configured to use absolute file names, you must set the emms-player-mpd-music-directory variable to the value of 'music_directory' in your MusicPD configuration. There are additional options available as well, but the defaults should be sufficient for most uses. Once you've done the above, run the 'M-x emms-cache-set-from-mpd-all' command to fill the Emms cache with the contents of your MusicPD database. The music in your MusicPD database should then be accessible via the Emms browser. You can set EMMS-PLAYER-MPD-SYNC-PLAYLIST to nil if your master Emms playlist contains only stored playlists. Commands provided ----------------- -- Function: emms-player-mpd-connect Connect to MusicPD and retrieve its current playlist. Afterward, the status of MusicPD will be tracked. -- Function: emms-player-mpd-disconnect Terminate the MusicPD client process and disconnect from MusicPD. -- Function: emms-player-mpd-show &optional insertp Describe the current Emms track in the minibuffer. If INSERTP is non-nil, insert the description into the current buffer instead. This function uses EMMS-SHOW-FORMAT to format the current track. It differs from 'emms-show' in that it asks MusicPD for the current track, rather than Emms. Updating the MusicPD database ............................. -- Function: emms-player-mpd-update-directory dir Cause the tracks in DIR to be updated in the MusicPD database. -- Function: emms-player-mpd-update-all Cause all tracks in the MusicPD music directory to be updated in the MusicPD database. emms-cache.el integration ......................... -- Function: emms-cache-set-from-mpd-directory dir Dump all MusicPD data from DIR into the Emms cache. This is useful to do when you have recently acquired new music. -- Function: emms-cache-set-from-mpd-all Dump all MusicPD data into the Emms cache. This is useful to do once, just before using emms-browser.el, in order to prime the cache. emms-volume.el integration .......................... To activate this, add the following to your .emacs. (require 'emms-volume) (setq emms-volume-change-function 'emms-volume-mpd-change)  File: emms.info, Node: Lyrics, Next: Volume, Prev: Music Player Daemon, Up: Top 24 Lyrics ********* We can display the lyrics of a song in time with the music using the 'emms-lyrics' package provided by the file 'emms-lyrics.el'. The lyrics files should have the extention ".lrc", and can be placed under either the same directory as the music files or EMMS-LYRICS-DIR. To add this feature we invoke: (require 'emms-lyrics) (emms-lyrics 1) There are a number of variables we can set to define the way that 'emms-lyrics' behaves, we can set these directly or by using the Customize feature in Emacs. -- User Option: emms-lyrics-display-on-minibuffer If non-nil, display lyrics on minibuffer. -- User Option: emms-lyrics-display-on-modeline If non-nil, display lyrics on modeline. -- User Option: emms-lyrics-dir Local lyrics repository. 'emms-lyrics-find-lyric' will look for lyrics in current directory(i.e., same as the music file) and this directory. -- User Option: emms-lyrics-display-format Format for displaying lyrics. "%s" will be replaced by the lyrics string. -- User Option: emms-lyrics-coding-system Coding system used in the output of lyrics. -- User Option: emms-lyrics-scroll-p Non-nil value will enable lyrics scrolling. -- User Option: emms-lyrics-scroll-timer-interval Interval between scroller timers. The shorter, the faster. We can control 'emms-lyrics' with the help of the following functions: -- Function: emms-lyrics-start Start displaying lyrics. -- Function: emms-lyrics-stop Stop displaying lyrics. -- Function: emms-lyrics-toggle-display-on-minibuffer Toggle display lyrics on minibufer. -- Function: emms-lyrics-toggle-display-on-modeline Toggle display lyrics on mode line. -- Function: emms-lyrics-enable Enable displaying Emms lyrics. -- Function: emms-lyrics-disable Disable displaying Emms lyrics. -- Function: emms-lyrics-toggle Toggle displaying Emms lyrics.  File: emms.info, Node: Volume, Next: Streaming Audio, Prev: Lyrics, Up: Top 25 Volume ********* We can use the 'emms-volume' package, as provided by the 'emms-volume.el' file, to manipulate the volume. -- User Option: emms-volume-change-amount The amount to use when raising or lowering the volume using the emms-volume interface. This should be a positive integer. -- Function: emms-volume-raise Increase the volume. -- Function: emms-volume-lower Decrease the volume. If you feel like binding those two functions to global keys -- don't do it or you'll miss the convenience of 'emms-volume-minor-mode'. Instead, bind the following two commands to some keys that you like. -- Function: emms-volume-mode-plus Raise volume and enable or extend the 'emms-volume-minor-mode' timeout. -- Function: emms-volume-mode-minus Lower volume and enable or extend the 'emms-volume-minor-mode' timeout. Example: (global-set-key (kbd "C-c +") 'emms-volume-mode-plus) (global-set-key (kbd "C-c -") 'emms-volume-mode-minus) Whenever you use one of these keys or call these functions with 'M-x', Emms will be put into 'emms-volume-minor-mode' for a short period defined by 'emms-volume-mode-timeout'. -- User Option: emms-volume-mode-timeout The timeout in amount of seconds used by 'emms-volume-minor-mode'. In this interval you can raise/lower the volume simply by pressing '+' or '-', which will also reset the timer to its initial value. So instead of pressing 'C-c +' six times to increase volume by six steps of 'emms-volume-change-amount', you would simply type 'C-c + + + + + +'. Emms can change volume with amixer, mpd, PulseAudio and mixerctl out of the box, see EMMS-VOLUME-CHANGE-FUNCTION.  File: emms.info, Node: Streaming Audio, Next: APE / FLAC Commands, Prev: Volume, Up: Top 26 Streaming Audio ****************** Emms is a great way to play streaming audio and internet radio. It is possible to add streaming playlists and URLs to any playlist, but Emms also comes with a built-in, eclectic list of streaming audio stations. (1) The 'emms-streams.el' package provides the command 'emms-streams'. Invoking 'emms-streams' will pull up an Emms playlist buffer and populate it with the built-in list of streaming audio sources. ---------- Footnotes ---------- (1) Emms has no affiliation of any kind with the streaming audio stations included, nor is their inclusion an endorsement of these stations. Instead, this is a collection of stations submitted to the project over the years by people who enjoy Emms. We hope you will enjoy them too, and invite you to send in your suggestions to add to the list.  File: emms.info, Node: APE / FLAC Commands, Next: Bookmarks, Prev: Streaming Audio, Up: Top 27 APE / FLAC Commands ********************** Often, a single APE or FLAC file contains a complete ablum. We can still play next or previous track in the ablum with the help of 'emms-cue.el' package, provided there is a corresponding cue sheet file. This package also defines 'emms-info-cueinfo' for retreiving the track information for APE / FLAC itself. To load 'emms-cue.el': (require 'emms-cue) (add-to-list 'emms-info-functions 'emms-info-cueinfo) -- Function: emms-cue-next Play next track from .cue file -- Function: emms-cue-previous Play previous track from .cue file  File: emms.info, Node: Bookmarks, Next: Managing Playlists, Prev: APE / FLAC Commands, Up: Top 28 Bookmarks ************ Emms can save a "temporal bookmark" in a media file via emms-bookmarks. The file 'emms-bookmarks.el' provides the package emms-bookmarks. While some media is playing, invoking 'M-x emms-bookmarks-add' will first pause the playback and then prompt for a name describing the bookmark. Tracks can have multiple bookmarks associated with them. To jump to the next and previous bookmarks in the current track invoke 'M-x emms-bookmarks-next' and 'M-x emms-bookmarks-prev' respectively. To clear all of the bookmarks for the current track invoke 'M-x emms-bookmarks-clear'.  File: emms.info, Node: Managing Playlists, Next: GNU FM, Prev: Bookmarks, Up: Top 29 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 'emms-metaplaylist-mode'. Start the playlist manager with 'M-x emms-metaplaylist-mode-go'. The playlist manager will list the playlists and mark the current one. The following commands are available: 'RET' Make the buffer at point the Emms playlist buffer and switch to it. 'SPC' Make the buffer at point the Emms playlist buffer (but do not switch to it). 'n' Move point to the next playlist. 'p' Move point to the previous playlist. 'g' Update the playlist manager buffer. 'C' Create a new Emms playlist buffer. 'C-k' Kill the Emms playlist buffer at point. 'c' Move point to the current playlist buffer. 'q' Kill the playlist manager.  File: emms.info, Node: GNU FM, Next: Copying, Prev: Managing Playlists, Up: Top 30 GNU FM ********* GNU FM (https://www.gnu.org/software/gnufm/) is free software for running music community websites. It was created for the music community site, Libre.fm (http://libre.fm/). Emms can send track information, and stream music from GNU FM servers using 'emms-librefm-scrobbler.el' and 'emms-librefm-stream.el', respectively. Emms is configured by default to use Libre.fm (http://libre.fm/), but can work with any GNU FM server by configuring the variable EMMS-LIBREFM-SCROBBLER-HANDSHAKE-URL to the URL of the GNU FM server. The recommended way of providing your credentials to the GNU FM server is by using an authinfo file. Add authentication to your auth-info file, typically '~/.authinfo.gpg', as: machine libre.fm login USERNAME password PASSWORD If you are using some other server than libre.fm, change "'libre.fm'" to match EMMS-LIBREFM-SCROBBLER-HANDSHAKE-URL. Alternatively, you can save the password in plaintext in your init-file by setting these variables: (setq emms-librefm-scrobbler-username "USERNAME" emms-librefm-scrobbler-password "PASSWORD") * Menu: * Uploading Track Information:: How to submit listened track information. * GNU FM Streaming:: Streaming music from a GNU FM server.  File: emms.info, Node: Uploading Track Information, Next: GNU FM Streaming, Up: GNU FM 30.1 Uploading Track Information ================================ GNU FM servers, such as Libre.fm can optionally store a user's listening habits using information sent to the website's server from the Emms. By utilizing the records of users' listening habits, the website aims to be able to recommend music to users by analyzing their musical taste. Load the feature into Emms with: (require 'emms-librefm-scrobbler) This feature can also be enabled via *Note Setup::, in the 'emms-all' setup level. Enable uploading the details of the tracks Emms plays to the GNU FM server with 'emms-librefm-scrobbler-enable'. The track's details will be uploaded to the server when the track's playback ends. You can disable this behavior with 'emms-librefm-scrobbler-disable'.  File: emms.info, Node: GNU FM Streaming, Prev: Uploading Track Information, Up: GNU FM 30.2 GNU FM Streaming ===================== If the GNU FM server provides a streaming music service you can take advantage of it by loading: (require 'emms-librefm-stream) This feature can also be enabled via *Note Setup::, in the 'emms-all' setup level. Then invoke 'emms-librefm-stream' and enter the URL of the station you wish to listen to, for example "librefm://globaltags/Classical".  File: emms.info, Node: Copying, Next: The GNU FDL, Prev: Extending Emms, Up: Top GNU General Public License ************************** Version 3, 29 June 2007 Copyright (C) 2007 Free Software Foundation, Inc. <http://fsf.org/> Everyone is permitted to copy and distribute verbatim copies of this license document, but changing it is not allowed. Preamble ======== The GNU General Public License is a free, copyleft license for software and other kinds of works. The licenses for most software and other practical works are designed to take away your freedom to share and change the works. By contrast, the GNU General Public License is intended to guarantee your freedom to share and change all versions of a program-to make sure it remains free software for all its users. We, the Free Software Foundation, use the GNU General Public License for most of our software; it applies also to any other work released this way by its authors. You can apply it to your programs, too. When we speak of free software, we are referring to freedom, not price. Our General Public Licenses are designed to make sure that you have the freedom to distribute copies of free software (and charge for them if you wish), that you receive source code or can get it if you want it, that you can change the software or use pieces of it in new free programs, and that you know you can do these things. To protect your rights, we need to prevent others from denying you these rights or asking you to surrender the rights. Therefore, you have certain responsibilities if you distribute copies of the software, or if you modify it: responsibilities to respect the freedom of others. For example, if you distribute copies of such a program, whether gratis or for a fee, you must pass on to the recipients the same freedoms that you received. You must make sure that they, too, receive or can get the source code. And you must show them these terms so they know their rights. Developers that use the GNU GPL protect your rights with two steps: (1) assert copyright on the software, and (2) offer you this License giving you legal permission to copy, distribute and/or modify it. For the developers' and authors' protection, the GPL clearly explains that there is no warranty for this free software. For both users' and authors' sake, the GPL requires that modified versions be marked as changed, so that their problems will not be attributed erroneously to authors of previous versions. Some devices are designed to deny users access to install or run modified versions of the software inside them, although the manufacturer can do so. This is fundamentally incompatible with the aim of protecting users' freedom to change the software. The systematic pattern of such abuse occurs in the area of products for individuals to use, which is precisely where it is most unacceptable. Therefore, we have designed this version of the GPL to prohibit the practice for those products. If such problems arise substantially in other domains, we stand ready to extend this provision to those domains in future versions of the GPL, as needed to protect the freedom of users. Finally, every program is threatened constantly by software patents. States should not allow patents to restrict development and use of software on general-purpose computers, but in those that do, we wish to avoid the special danger that patents applied to a free program could make it effectively proprietary. To prevent this, the GPL assures that patents cannot be used to render the program non-free. The precise terms and conditions for copying, distribution and modification follow. TERMS AND CONDITIONS 0. Definitions. "This License" refers to version 3 of the GNU General Public License. "Copyright" also means copyright-like laws that apply to other kinds of works, such as semiconductor masks. "The Program" refers to any copyrightable work licensed under this License. Each licensee is addressed as "you". "Licensees" and "recipients" may be individuals or organizations. To "modify" a work means to copy from or adapt all or part of the work in a fashion requiring copyright permission, other than the making of an exact copy. The resulting work is called a "modified version" of the earlier work or a work "based on" the earlier work. A "covered work" means either the unmodified Program or a work based on the Program. To "propagate" a work means to do anything with it that, without permission, would make you directly or secondarily liable for infringement under applicable copyright law, except executing it on a computer or modifying a private copy. Propagation includes copying, distribution (with or without modification), making available to the public, and in some countries other activities as well. To "convey" a work means any kind of propagation that enables other parties to make or receive copies. Mere interaction with a user through a computer network, with no transfer of a copy, is not conveying. An interactive user interface displays "Appropriate Legal Notices" to the extent that it includes a convenient and prominently visible feature that (1) displays an appropriate copyright notice, and (2) tells the user that there is no warranty for the work (except to the extent that warranties are provided), that licensees may convey the work under this License, and how to view a copy of this License. If the interface presents a list of user commands or options, such as a menu, a prominent item in the list meets this criterion. 1. Source Code. The "source code" for a work means the preferred form of the work for making modifications to it. "Object code" means any non-source form of a work. A "Standard Interface" means an interface that either is an official standard defined by a recognized standards body, or, in the case of interfaces specified for a particular programming language, one that is widely used among developers working in that language. The "System Libraries" of an executable work include anything, other than the work as a whole, that (a) is included in the normal form of packaging a Major Component, but which is not part of that Major Component, and (b) serves only to enable use of the work with that Major Component, or to implement a Standard Interface for which an implementation is available to the public in source code form. A "Major Component", in this context, means a major essential component (kernel, window system, and so on) of the specific operating system (if any) on which the executable work runs, or a compiler used to produce the work, or an object code interpreter used to run it. The "Corresponding Source" for a work in object code form means all the source code needed to generate, install, and (for an executable work) run the object code and to modify the work, including scripts to control those activities. However, it does not include the work's System Libraries, or general-purpose tools or generally available free programs which are used unmodified in performing those activities but which are not part of the work. For example, Corresponding Source includes interface definition files associated with source files for the work, and the source code for shared libraries and dynamically linked subprograms that the work is specifically designed to require, such as by intimate data communication or control flow between those subprograms and other parts of the work. The Corresponding Source need not include anything that users can regenerate automatically from other parts of the Corresponding Source. The Corresponding Source for a work in source code form is that same work. 2. Basic Permissions. All rights granted under this License are granted for the term of copyright on the Program, and are irrevocable provided the stated conditions are met. This License explicitly affirms your unlimited permission to run the unmodified Program. The output from running a covered work is covered by this License only if the output, given its content, constitutes a covered work. This License acknowledges your rights of fair use or other equivalent, as provided by copyright law. You may make, run and propagate covered works that you do not convey, without conditions so long as your license otherwise remains in force. You may convey covered works to others for the sole purpose of having them make modifications exclusively for you, or provide you with facilities for running those works, provided that you comply with the terms of this License in conveying all material for which you do not control copyright. Those thus making or running the covered works for you must do so exclusively on your behalf, under your direction and control, on terms that prohibit them from making any copies of your copyrighted material outside their relationship with you. Conveying under any other circumstances is permitted solely under the conditions stated below. Sublicensing is not allowed; section 10 makes it unnecessary. 3. Protecting Users' Legal Rights From Anti-Circumvention Law. No covered work shall be deemed part of an effective technological measure under any applicable law fulfilling obligations under article 11 of the WIPO copyright treaty adopted on 20 December 1996, or similar laws prohibiting or restricting circumvention of such measures. When you convey a covered work, you waive any legal power to forbid circumvention of technological measures to the extent such circumvention is effected by exercising rights under this License with respect to the covered work, and you disclaim any intention to limit operation or modification of the work as a means of enforcing, against the work's users, your or third parties' legal rights to forbid circumvention of technological measures. 4. Conveying Verbatim Copies. You may convey verbatim copies of the Program's source code as you receive it, in any medium, provided that you conspicuously and appropriately publish on each copy an appropriate copyright notice; keep intact all notices stating that this License and any non-permissive terms added in accord with section 7 apply to the code; keep intact all notices of the absence of any warranty; and give all recipients a copy of this License along with the Program. You may charge any price or no price for each copy that you convey, and you may offer support or warranty protection for a fee. 5. Conveying Modified Source Versions. You may convey a work based on the Program, or the modifications to produce it from the Program, in the form of source code under the terms of section 4, provided that you also meet all of these conditions: a. The work must carry prominent notices stating that you modified it, and giving a relevant date. b. The work must carry prominent notices stating that it is released under this License and any conditions added under section 7. This requirement modifies the requirement in section 4 to "keep intact all notices". c. You must license the entire work, as a whole, under this License to anyone who comes into possession of a copy. This License will therefore apply, along with any applicable section 7 additional terms, to the whole of the work, and all its parts, regardless of how they are packaged. This License gives no permission to license the work in any other way, but it does not invalidate such permission if you have separately received it. d. If the work has interactive user interfaces, each must display Appropriate Legal Notices; however, if the Program has interactive interfaces that do not display Appropriate Legal Notices, your work need not make them do so. A compilation of a covered work with other separate and independent works, which are not by their nature extensions of the covered work, and which are not combined with it such as to form a larger program, in or on a volume of a storage or distribution medium, is called an "aggregate" if the compilation and its resulting copyright are not used to limit the access or legal rights of the compilation's users beyond what the individual works permit. Inclusion of a covered work in an aggregate does not cause this License to apply to the other parts of the aggregate. 6. Conveying Non-Source Forms. You may convey a covered work in object code form under the terms of sections 4 and 5, provided that you also convey the machine-readable Corresponding Source under the terms of this License, in one of these ways: a. Convey the object code in, or embodied in, a physical product (including a physical distribution medium), accompanied by the Corresponding Source fixed on a durable physical medium customarily used for software interchange. b. Convey the object code in, or embodied in, a physical product (including a physical distribution medium), accompanied by a written offer, valid for at least three years and valid for as long as you offer spare parts or customer support for that product model, to give anyone who possesses the object code either (1) a copy of the Corresponding Source for all the software in the product that is covered by this License, on a durable physical medium customarily used for software interchange, for a price no more than your reasonable cost of physically performing this conveying of source, or (2) access to copy the Corresponding Source from a network server at no charge. c. Convey individual copies of the object code with a copy of the written offer to provide the Corresponding Source. This alternative is allowed only occasionally and noncommercially, and only if you received the object code with such an offer, in accord with subsection 6b. d. Convey the object code by offering access from a designated place (gratis or for a charge), and offer equivalent access to the Corresponding Source in the same way through the same place at no further charge. You need not require recipients to copy the Corresponding Source along with the object code. If the place to copy the object code is a network server, the Corresponding Source may be on a different server (operated by you or a third party) that supports equivalent copying facilities, provided you maintain clear directions next to the object code saying where to find the Corresponding Source. Regardless of what server hosts the Corresponding Source, you remain obligated to ensure that it is available for as long as needed to satisfy these requirements. e. Convey the object code using peer-to-peer transmission, provided you inform other peers where the object code and Corresponding Source of the work are being offered to the general public at no charge under subsection 6d. A separable portion of the object code, whose source code is excluded from the Corresponding Source as a System Library, need not be included in conveying the object code work. A "User Product" is either (1) a "consumer product", which means any tangible personal property which is normally used for personal, family, or household purposes, or (2) anything designed or sold for incorporation into a dwelling. In determining whether a product is a consumer product, doubtful cases shall be resolved in favor of coverage. For a particular product received by a particular user, "normally used" refers to a typical or common use of that class of product, regardless of the status of the particular user or of the way in which the particular user actually uses, or expects or is expected to use, the product. A product is a consumer product regardless of whether the product has substantial commercial, industrial or non-consumer uses, unless such uses represent the only significant mode of use of the product. "Installation Information" for a User Product means any methods, procedures, authorization keys, or other information required to install and execute modified versions of a covered work in that User Product from a modified version of its Corresponding Source. The information must suffice to ensure that the continued functioning of the modified object code is in no case prevented or interfered with solely because modification has been made. If you convey an object code work under this section in, or with, or specifically for use in, a User Product, and the conveying occurs as part of a transaction in which the right of possession and use of the User Product is transferred to the recipient in perpetuity or for a fixed term (regardless of how the transaction is characterized), the Corresponding Source conveyed under this section must be accompanied by the Installation Information. But this requirement does not apply if neither you nor any third party retains the ability to install modified object code on the User Product (for example, the work has been installed in ROM). The requirement to provide Installation Information does not include a requirement to continue to provide support service, warranty, or updates for a work that has been modified or installed by the recipient, or for the User Product in which it has been modified or installed. Access to a network may be denied when the modification itself materially and adversely affects the operation of the network or violates the rules and protocols for communication across the network. Corresponding Source conveyed, and Installation Information provided, in accord with this section must be in a format that is publicly documented (and with an implementation available to the public in source code form), and must require no special password or key for unpacking, reading or copying. 7. Additional Terms. "Additional permissions" are terms that supplement the terms of this License by making exceptions from one or more of its conditions. Additional permissions that are applicable to the entire Program shall be treated as though they were included in this License, to the extent that they are valid under applicable law. If additional permissions apply only to part of the Program, that part may be used separately under those permissions, but the entire Program remains governed by this License without regard to the additional permissions. When you convey a copy of a covered work, you may at your option remove any additional permissions from that copy, or from any part of it. (Additional permissions may be written to require their own removal in certain cases when you modify the work.) You may place additional permissions on material, added by you to a covered work, for which you have or can give appropriate copyright permission. Notwithstanding any other provision of this License, for material you add to a covered work, you may (if authorized by the copyright holders of that material) supplement the terms of this License with terms: a. Disclaiming warranty or limiting liability differently from the terms of sections 15 and 16 of this License; or b. Requiring preservation of specified reasonable legal notices or author attributions in that material or in the Appropriate Legal Notices displayed by works containing it; or c. Prohibiting misrepresentation of the origin of that material, or requiring that modified versions of such material be marked in reasonable ways as different from the original version; or d. Limiting the use for publicity purposes of names of licensors or authors of the material; or e. Declining to grant rights under trademark law for use of some trade names, trademarks, or service marks; or f. Requiring indemnification of licensors and authors of that material by anyone who conveys the material (or modified versions of it) with contractual assumptions of liability to the recipient, for any liability that these contractual assumptions directly impose on those licensors and authors. All other non-permissive additional terms are considered "further restrictions" within the meaning of section 10. If the Program as you received it, or any part of it, contains a notice stating that it is governed by this License along with a term that is a further restriction, you may remove that term. If a license document contains a further restriction but permits relicensing or conveying under this License, you may add to a covered work material governed by the terms of that license document, provided that the further restriction does not survive such relicensing or conveying. If you add terms to a covered work in accord with this section, you must place, in the relevant source files, a statement of the additional terms that apply to those files, or a notice indicating where to find the applicable terms. Additional terms, permissive or non-permissive, may be stated in the form of a separately written license, or stated as exceptions; the above requirements apply either way. 8. Termination. You may not propagate or modify a covered work except as expressly provided under this License. Any attempt otherwise to propagate or modify it is void, and will automatically terminate your rights under this License (including any patent licenses granted under the third paragraph of section 11). However, if you cease all violation of this License, then your license from a particular copyright holder is reinstated (a) provisionally, unless and until the copyright holder explicitly and finally terminates your license, and (b) permanently, if the copyright holder fails to notify you of the violation by some reasonable means prior to 60 days after the cessation. Moreover, your license from a particular copyright holder is reinstated permanently if the copyright holder notifies you of the violation by some reasonable means, this is the first time you have received notice of violation of this License (for any work) from that copyright holder, and you cure the violation prior to 30 days after your receipt of the notice. Termination of your rights under this section does not terminate the licenses of parties who have received copies or rights from you under this License. If your rights have been terminated and not permanently reinstated, you do not qualify to receive new licenses for the same material under section 10. 9. Acceptance Not Required for Having Copies. You are not required to accept this License in order to receive or run a copy of the Program. Ancillary propagation of a covered work occurring solely as a consequence of using peer-to-peer transmission to receive a copy likewise does not require acceptance. However, nothing other than this License grants you permission to propagate or modify any covered work. These actions infringe copyright if you do not accept this License. Therefore, by modifying or propagating a covered work, you indicate your acceptance of this License to do so. 10. Automatic Licensing of Downstream Recipients. Each time you convey a covered work, the recipient automatically receives a license from the original licensors, to run, modify and propagate that work, subject to this License. You are not responsible for enforcing compliance by third parties with this License. An "entity transaction" is a transaction transferring control of an organization, or substantially all assets of one, or subdividing an organization, or merging organizations. If propagation of a covered work results from an entity transaction, each party to that transaction who receives a copy of the work also receives whatever licenses to the work the party's predecessor in interest had or could give under the previous paragraph, plus a right to possession of the Corresponding Source of the work from the predecessor in interest, if the predecessor has it or can get it with reasonable efforts. You may not impose any further restrictions on the exercise of the rights granted or affirmed under this License. For example, you may not impose a license fee, royalty, or other charge for exercise of rights granted under this License, and you may not initiate litigation (including a cross-claim or counterclaim in a lawsuit) alleging that any patent claim is infringed by making, using, selling, offering for sale, or importing the Program or any portion of it. 11. Patents. A "contributor" is a copyright holder who authorizes use under this License of the Program or a work on which the Program is based. The work thus licensed is called the contributor's "contributor version". A contributor's "essential patent claims" are all patent claims owned or controlled by the contributor, whether already acquired or hereafter acquired, that would be infringed by some manner, permitted by this License, of making, using, or selling its contributor version, but do not include claims that would be infringed only as a consequence of further modification of the contributor version. For purposes of this definition, "control" includes the right to grant patent sublicenses in a manner consistent with the requirements of this License. Each contributor grants you a non-exclusive, worldwide, royalty-free patent license under the contributor's essential patent claims, to make, use, sell, offer for sale, import and otherwise run, modify and propagate the contents of its contributor version. In the following three paragraphs, a "patent license" is any express agreement or commitment, however denominated, not to enforce a patent (such as an express permission to practice a patent or covenant not to sue for patent infringement). To "grant" such a patent license to a party means to make such an agreement or commitment not to enforce a patent against the party. If you convey a covered work, knowingly relying on a patent license, and the Corresponding Source of the work is not available for anyone to copy, free of charge and under the terms of this License, through a publicly available network server or other readily accessible means, then you must either (1) cause the Corresponding Source to be so available, or (2) arrange to deprive yourself of the benefit of the patent license for this particular work, or (3) arrange, in a manner consistent with the requirements of this License, to extend the patent license to downstream recipients. "Knowingly relying" means you have actual knowledge that, but for the patent license, your conveying the covered work in a country, or your recipient's use of the covered work in a country, would infringe one or more identifiable patents in that country that you have reason to believe are valid. If, pursuant to or in connection with a single transaction or arrangement, you convey, or propagate by procuring conveyance of, a covered work, and grant a patent license to some of the parties receiving the covered work authorizing them to use, propagate, modify or convey a specific copy of the covered work, then the patent license you grant is automatically extended to all recipients of the covered work and works based on it. A patent license is "discriminatory" if it does not include within the scope of its coverage, prohibits the exercise of, or is conditioned on the non-exercise of one or more of the rights that are specifically granted under this License. You may not convey a covered work if you are a party to an arrangement with a third party that is in the business of distributing software, under which you make payment to the third party based on the extent of your activity of conveying the work, and under which the third party grants, to any of the parties who would receive the covered work from you, a discriminatory patent license (a) in connection with copies of the covered work conveyed by you (or copies made from those copies), or (b) primarily for and in connection with specific products or compilations that contain the covered work, unless you entered into that arrangement, or that patent license was granted, prior to 28 March 2007. Nothing in this License shall be construed as excluding or limiting any implied license or other defenses to infringement that may otherwise be available to you under applicable patent law. 12. No Surrender of Others' Freedom. If conditions are imposed on you (whether by court order, agreement or otherwise) that contradict the conditions of this License, they do not excuse you from the conditions of this License. If you cannot convey a covered work so as to satisfy simultaneously your obligations under this License and any other pertinent obligations, then as a consequence you may not convey it at all. For example, if you agree to terms that obligate you to collect a royalty for further conveying from those to whom you convey the Program, the only way you could satisfy both those terms and this License would be to refrain entirely from conveying the Program. 13. Use with the GNU Affero General Public License. Notwithstanding any other provision of this License, you have permission to link or combine any covered work with a work licensed under version 3 of the GNU Affero General Public License into a single combined work, and to convey the resulting work. The terms of this License will continue to apply to the part which is the covered work, but the special requirements of the GNU Affero General Public License, section 13, concerning interaction through a network will apply to the combination as such. 14. Revised Versions of this License. The Free Software Foundation may publish revised and/or new versions of the GNU General Public License from time to time. Such new versions will be similar in spirit to the present version, but may differ in detail to address new problems or concerns. Each version is given a distinguishing version number. If the Program specifies that a certain numbered version of the GNU General Public License "or any later version" applies to it, you have the option of following the terms and conditions either of that numbered version or of any later version published by the Free Software Foundation. If the Program does not specify a version number of the GNU General Public License, you may choose any version ever published by the Free Software Foundation. If the Program specifies that a proxy can decide which future versions of the GNU General Public License can be used, that proxy's public statement of acceptance of a version permanently authorizes you to choose that version for the Program. Later license versions may give you additional or different permissions. However, no additional obligations are imposed on any author or copyright holder as a result of your choosing to follow a later version. 15. Disclaimer of Warranty. THERE IS NO WARRANTY FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING, REPAIR OR CORRECTION. 16. Limitation of Liability. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MODIFIES AND/OR CONVEYS THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES. 17. Interpretation of Sections 15 and 16. If the disclaimer of warranty and limitation of liability provided above cannot be given local legal effect according to their terms, reviewing courts shall apply local law that most closely approximates an absolute waiver of all civil liability in connection with the Program, unless a warranty or assumption of liability accompanies a copy of the Program in return for a fee. END OF TERMS AND CONDITIONS How to Apply These Terms to Your New Programs ============================================= If you develop a new program, and you want it to be of the greatest possible use to the public, the best way to achieve this is to make it free software which everyone can redistribute and change under these terms. To do so, attach the following notices to the program. It is safest to attach them to the start of each source file to most effectively state the exclusion of warranty; and each file should have at least the "copyright" line and a pointer to where the full notice is found. ONE LINE TO GIVE THE PROGRAM'S NAME AND A BRIEF IDEA OF WHAT IT DOES. Copyright (C) YEAR NAME OF AUTHOR This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program. If not, see <http://www.gnu.org/licenses/>. Also add information on how to contact you by electronic and paper mail. If the program does terminal interaction, make it output a short notice like this when it starts in an interactive mode: PROGRAM Copyright (C) YEAR NAME OF AUTHOR This program comes with ABSOLUTELY NO WARRANTY; for details type 'show w'. This is free software, and you are welcome to redistribute it under certain conditions; type 'show c' for details. The hypothetical commands 'show w' and 'show c' should show the appropriate parts of the General Public License. Of course, your program's commands might be different; for a GUI interface, you would use an "about box". You should also get your employer (if you work as a programmer) or school, if any, to sign a "copyright disclaimer" for the program, if necessary. For more information on this, and how to apply and follow the GNU GPL, see <http://www.gnu.org/licenses/>. The GNU General Public License does not permit incorporating your program into proprietary programs. If your program is a subroutine library, you may consider it more useful to permit linking proprietary applications with the library. If this is what you want to do, use the GNU Lesser General Public License instead of this License. But first, please read <http://www.gnu.org/philosophy/why-not-lgpl.html>.  File: emms.info, Node: The GNU FDL, Next: Concept Index, Prev: Copying, Up: Top 31 GNU Free Documentation License ********************************* Version 1.2, November 2002 Copyright (C) 2000,2001,2002 Free Software Foundation, Inc. 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA Everyone is permitted to copy and distribute verbatim copies of this license document, but changing it is not allowed. 0. PREAMBLE The purpose of this License is to make a manual, textbook, or other functional and useful document "free" in the sense of freedom: to assure everyone the effective freedom to copy and redistribute it, with or without modifying it, either commercially or noncommercially. Secondarily, this License preserves for the author and publisher a way to get credit for their work, while not being considered responsible for modifications made by others. This License is a kind of "copyleft", which means that derivative works of the document must themselves be free in the same sense. It complements the GNU General Public License, which is a copyleft license designed for free software. We have designed this License in order to use it for manuals for free software, because free software needs free documentation: a free program should come with manuals providing the same freedoms that the software does. But this License is not limited to software manuals; it can be used for any textual work, regardless of subject matter or whether it is published as a printed book. We recommend this License principally for works whose purpose is instruction or reference. 1. APPLICABILITY AND DEFINITIONS This License applies to any manual or other work, in any medium, that contains a notice placed by the copyright holder saying it can be distributed under the terms of this License. Such a notice grants a world-wide, royalty-free license, unlimited in duration, to use that work under the conditions stated herein. The "Document", below, refers to any such manual or work. Any member of the public is a licensee, and is addressed as "you". You accept the license if you copy, modify or distribute the work in a way requiring permission under copyright law. A "Modified Version" of the Document means any work containing the Document or a portion of it, either copied verbatim, or with modifications and/or translated into another language. A "Secondary Section" is a named appendix or a front-matter section of the Document that deals exclusively with the relationship of the publishers or authors of the Document to the Document's overall subject (or to related matters) and contains nothing that could fall directly within that overall subject. (Thus, if the Document is in part a textbook of mathematics, a Secondary Section may not explain any mathematics.) The relationship could be a matter of historical connection with the subject or with related matters, or of legal, commercial, philosophical, ethical or political position regarding them. The "Invariant Sections" are certain Secondary Sections whose titles are designated, as being those of Invariant Sections, in the notice that says that the Document is released under this License. If a section does not fit the above definition of Secondary then it is not allowed to be designated as Invariant. The Document may contain zero Invariant Sections. If the Document does not identify any Invariant Sections then there are none. The "Cover Texts" are certain short passages of text that are listed, as Front-Cover Texts or Back-Cover Texts, in the notice that says that the Document is released under this License. A Front-Cover Text may be at most 5 words, and a Back-Cover Text may be at most 25 words. A "Transparent" copy of the Document means a machine-readable copy, represented in a format whose specification is available to the general public, that is suitable for revising the document straightforwardly with generic text editors or (for images composed of pixels) generic paint programs or (for drawings) some widely available drawing editor, and that is suitable for input to text formatters or for automatic translation to a variety of formats suitable for input to text formatters. A copy made in an otherwise Transparent file format whose markup, or absence of markup, has been arranged to thwart or discourage subsequent modification by readers is not Transparent. An image format is not Transparent if used for any substantial amount of text. A copy that is not "Transparent" is called "Opaque". Examples of suitable formats for Transparent copies include plain ASCII without markup, Texinfo input format, LaTeX input format, SGML or XML using a publicly available DTD, and standard-conforming simple HTML, PostScript or PDF designed for human modification. Examples of transparent image formats include PNG, XCF and JPG. Opaque formats include proprietary formats that can be read and edited only by proprietary word processors, SGML or XML for which the DTD and/or processing tools are not generally available, and the machine-generated HTML, PostScript or PDF produced by some word processors for output purposes only. The "Title Page" means, for a printed book, the title page itself, plus such following pages as are needed to hold, legibly, the material this License requires to appear in the title page. For works in formats which do not have any title page as such, "Title Page" means the text near the most prominent appearance of the work's title, preceding the beginning of the body of the text. A section "Entitled XYZ" means a named subunit of the Document whose title either is precisely XYZ or contains XYZ in parentheses following text that translates XYZ in another language. (Here XYZ stands for a specific section name mentioned below, such as "Acknowledgements", "Dedications", "Endorsements", or "History".) To "Preserve the Title" of such a section when you modify the Document means that it remains a section "Entitled XYZ" according to this definition. The Document may include Warranty Disclaimers next to the notice which states that this License applies to the Document. These Warranty Disclaimers are considered to be included by reference in this License, but only as regards disclaiming warranties: any other implication that these Warranty Disclaimers may have is void and has no effect on the meaning of this License. 2. VERBATIM COPYING You may copy and distribute the Document in any medium, either commercially or noncommercially, provided that this License, the copyright notices, and the license notice saying this License applies to the Document are reproduced in all copies, and that you add no other conditions whatsoever to those of this License. You may not use technical measures to obstruct or control the reading or further copying of the copies you make or distribute. However, you may accept compensation in exchange for copies. If you distribute a large enough number of copies you must also follow the conditions in section 3. You may also lend copies, under the same conditions stated above, and you may publicly display copies. 3. COPYING IN QUANTITY If you publish printed copies (or copies in media that commonly have printed covers) of the Document, numbering more than 100, and the Document's license notice requires Cover Texts, you must enclose the copies in covers that carry, clearly and legibly, all these Cover Texts: Front-Cover Texts on the front cover, and Back-Cover Texts on the back cover. Both covers must also clearly and legibly identify you as the publisher of these copies. The front cover must present the full title with all words of the title equally prominent and visible. You may add other material on the covers in addition. Copying with changes limited to the covers, as long as they preserve the title of the Document and satisfy these conditions, can be treated as verbatim copying in other respects. If the required texts for either cover are too voluminous to fit legibly, you should put the first ones listed (as many as fit reasonably) on the actual cover, and continue the rest onto adjacent pages. If you publish or distribute Opaque copies of the Document numbering more than 100, you must either include a machine-readable Transparent copy along with each Opaque copy, or state in or with each Opaque copy a computer-network location from which the general network-using public has access to download using public-standard network protocols a complete Transparent copy of the Document, free of added material. If you use the latter option, you must take reasonably prudent steps, when you begin distribution of Opaque copies in quantity, to ensure that this Transparent copy will remain thus accessible at the stated location until at least one year after the last time you distribute an Opaque copy (directly or through your agents or retailers) of that edition to the public. It is requested, but not required, that you contact the authors of the Document well before redistributing any large number of copies, to give them a chance to provide you with an updated version of the Document. 4. MODIFICATIONS You may copy and distribute a Modified Version of the Document under the conditions of sections 2 and 3 above, provided that you release the Modified Version under precisely this License, with the Modified Version filling the role of the Document, thus licensing distribution and modification of the Modified Version to whoever possesses a copy of it. In addition, you must do these things in the Modified Version: A. Use in the Title Page (and on the covers, if any) a title distinct from that of the Document, and from those of previous versions (which should, if there were any, be listed in the History section of the Document). You may use the same title as a previous version if the original publisher of that version gives permission. B. List on the Title Page, as authors, one or more persons or entities responsible for authorship of the modifications in the Modified Version, together with at least five of the principal authors of the Document (all of its principal authors, if it has fewer than five), unless they release you from this requirement. C. State on the Title page the name of the publisher of the Modified Version, as the publisher. D. Preserve all the copyright notices of the Document. E. Add an appropriate copyright notice for your modifications adjacent to the other copyright notices. F. Include, immediately after the copyright notices, a license notice giving the public permission to use the Modified Version under the terms of this License, in the form shown in the Addendum below. G. Preserve in that license notice the full lists of Invariant Sections and required Cover Texts given in the Document's license notice. H. Include an unaltered copy of this License. I. Preserve the section Entitled "History", Preserve its Title, and add to it an item stating at least the title, year, new authors, and publisher of the Modified Version as given on the Title Page. If there is no section Entitled "History" in the Document, create one stating the title, year, authors, and publisher of the Document as given on its Title Page, then add an item describing the Modified Version as stated in the previous sentence. J. Preserve the network location, if any, given in the Document for public access to a Transparent copy of the Document, and likewise the network locations given in the Document for previous versions it was based on. These may be placed in the "History" section. You may omit a network location for a work that was published at least four years before the Document itself, or if the original publisher of the version it refers to gives permission. K. For any section Entitled "Acknowledgements" or "Dedications", Preserve the Title of the section, and preserve in the section all the substance and tone of each of the contributor acknowledgements and/or dedications given therein. L. Preserve all the Invariant Sections of the Document, unaltered in their text and in their titles. Section numbers or the equivalent are not considered part of the section titles. M. Delete any section Entitled "Endorsements". Such a section may not be included in the Modified Version. N. Do not retitle any existing section to be Entitled "Endorsements" or to conflict in title with any Invariant Section. O. Preserve any Warranty Disclaimers. If the Modified Version includes new front-matter sections or appendices that qualify as Secondary Sections and contain no material copied from the Document, you may at your option designate some or all of these sections as invariant. To do this, add their titles to the list of Invariant Sections in the Modified Version's license notice. These titles must be distinct from any other section titles. You may add a section Entitled "Endorsements", provided it contains nothing but endorsements of your Modified Version by various parties--for example, statements of peer review or that the text has been approved by an organization as the authoritative definition of a standard. You may add a passage of up to five words as a Front-Cover Text, and a passage of up to 25 words as a Back-Cover Text, to the end of the list of Cover Texts in the Modified Version. Only one passage of Front-Cover Text and one of Back-Cover Text may be added by (or through arrangements made by) any one entity. If the Document already includes a cover text for the same cover, previously added by you or by arrangement made by the same entity you are acting on behalf of, you may not add another; but you may replace the old one, on explicit permission from the previous publisher that added the old one. The author(s) and publisher(s) of the Document do not by this License give permission to use their names for publicity for or to assert or imply endorsement of any Modified Version. 5. COMBINING DOCUMENTS You may combine the Document with other documents released under this License, under the terms defined in section 4 above for modified versions, provided that you include in the combination all of the Invariant Sections of all of the original documents, unmodified, and list them all as Invariant Sections of your combined work in its license notice, and that you preserve all their Warranty Disclaimers. The combined work need only contain one copy of this License, and multiple identical Invariant Sections may be replaced with a single copy. If there are multiple Invariant Sections with the same name but different contents, make the title of each such section unique by adding at the end of it, in parentheses, the name of the original author or publisher of that section if known, or else a unique number. Make the same adjustment to the section titles in the list of Invariant Sections in the license notice of the combined work. In the combination, you must combine any sections Entitled "History" in the various original documents, forming one section Entitled "History"; likewise combine any sections Entitled "Acknowledgements", and any sections Entitled "Dedications". You must delete all sections Entitled "Endorsements." 6. COLLECTIONS OF DOCUMENTS You may make a collection consisting of the Document and other documents released under this License, and replace the individual copies of this License in the various documents with a single copy that is included in the collection, provided that you follow the rules of this License for verbatim copying of each of the documents in all other respects. You may extract a single document from such a collection, and distribute it individually under this License, provided you insert a copy of this License into the extracted document, and follow this License in all other respects regarding verbatim copying of that document. 7. AGGREGATION WITH INDEPENDENT WORKS A compilation of the Document or its derivatives with other separate and independent documents or works, in or on a volume of a storage or distribution medium, is called an "aggregate" if the copyright resulting from the compilation is not used to limit the legal rights of the compilation's users beyond what the individual works permit. When the Document is included in an aggregate, this License does not apply to the other works in the aggregate which are not themselves derivative works of the Document. If the Cover Text requirement of section 3 is applicable to these copies of the Document, then if the Document is less than one half of the entire aggregate, the Document's Cover Texts may be placed on covers that bracket the Document within the aggregate, or the electronic equivalent of covers if the Document is in electronic form. Otherwise they must appear on printed covers that bracket the whole aggregate. 8. TRANSLATION Translation is considered a kind of modification, so you may distribute translations of the Document under the terms of section 4. Replacing Invariant Sections with translations requires special permission from their copyright holders, but you may include translations of some or all Invariant Sections in addition to the original versions of these Invariant Sections. You may include a translation of this License, and all the license notices in the Document, and any Warranty Disclaimers, provided that you also include the original English version of this License and the original versions of those notices and disclaimers. In case of a disagreement between the translation and the original version of this License or a notice or disclaimer, the original version will prevail. If a section in the Document is Entitled "Acknowledgements", "Dedications", or "History", the requirement (section 4) to Preserve its Title (section 1) will typically require changing the actual title. 9. TERMINATION You may not copy, modify, sublicense, or distribute the Document except as expressly provided for under this License. Any other attempt to copy, modify, sublicense or distribute the Document is void, and will automatically terminate your rights under this License. However, parties who have received copies, or rights, from you under this License will not have their licenses terminated so long as such parties remain in full compliance. 10. FUTURE REVISIONS OF THIS LICENSE The Free Software Foundation may publish new, revised versions of the GNU Free Documentation License from time to time. Such new versions will be similar in spirit to the present version, but may differ in detail to address new problems or concerns. See <http://www.gnu.org/copyleft/>. Each version of the License is given a distinguishing version number. If the Document specifies that a particular numbered version of this License "or any later version" applies to it, you have the option of following the terms and conditions either of that specified version or of any later version that has been published (not as a draft) by the Free Software Foundation. If the Document does not specify a version number of this License, you may choose any version ever published (not as a draft) by the Free Software Foundation. 31.1 ADDENDUM: How to use this License for your documents ========================================================= To use this License in a document you have written, include a copy of the License in the document and put the following copyright and license notices just after the title page: Copyright (C) YEAR YOUR NAME. Permission is granted to copy, distribute and/or modify this document under the terms of the GNU Free Documentation License, Version 1.2 or any later version published by the Free Software Foundation; with no Invariant Sections, no Front-Cover Texts, and no Back-Cover Texts. A copy of the license is included in the section entitled ``GNU Free Documentation License''. If you have Invariant Sections, Front-Cover Texts and Back-Cover Texts, replace the "with...Texts." line with this: with the Invariant Sections being LIST THEIR TITLES, with the Front-Cover Texts being LIST, and with the Back-Cover Texts being LIST. If you have Invariant Sections without Cover Texts, or some other combination of the three, merge those two alternatives to suit the situation. If your document contains nontrivial examples of program code, we recommend releasing these examples in parallel under your choice of free software license, such as the GNU General Public License, to permit their use in free software.  File: emms.info, Node: Concept Index, Next: Function Index, Prev: The GNU FDL, Up: Top Concept Index ************* �[index�] * Menu: * adding functionality: Hooks. (line 6) * advanced player: More Complex Player. (line 6) * basic commands: Basic Commands. (line 6) * basic functions: Core Functions. (line 6) * basic player: Simple Player for `play'. (line 6) * commands, basic: Basic Commands. (line 6) * compiling: Compiling Emms. (line 6) * complex player: More Complex Player. (line 6) * Configuration: Configuration. (line 6) * core file: The Core File. (line 6) * core functions: Core Functions. (line 6) * defining info methods: Defining Info Methods. (line 6) * defining new players: New Player. (line 6) * defining players: Extending Emms. (line 6) * display emms information: Emms Mode Line. (line 6) * FDL, GNU Free Documentation License: The GNU FDL. (line 6) * files: Finding files and speed. (line 6) * format: Formats and Freedom. (line 6) * freedom: Formats and Freedom. (line 6) * GNU FM: GNU FM. (line 6) * heart of Emms: The Core File. (line 6) * hooks: Hooks. (line 6) * info tags: Track Information. (line 6) * installation: Installation. (line 6) * Interactive Playlists: Interactive Playlists. (line 6) * internet radio: Streaming Audio. (line 6) * introduction: Introduction. (line 6) * limiting: Limiting. (line 6) * lyrics: Lyrics. (line 6) * mailing list: Getting Help. (line 6) * Markable Playlists: Markable Playlists. (line 6) * mode line: Emms Mode Line. (line 6) * mpd: Music Player Daemon. (line 6) * music player daemon: Music Player Daemon. (line 6) * new player: New Player. (line 6) * new players: Extending Emms. (line 6) * new players, defining: Extending Emms. (line 6) * options: User Variables. (line 6) * organizing tracks and media: Playlists. (line 6) * players, simple: Simple Players. (line 6) * playlist: Limiting. (line 6) * primitive functions: The Core File. (line 6) * primitive player: Simple Player for `play'. (line 6) * quick setup: Setup. (line 6) * remote interface: Music Player Daemon. (line 6) * setting up Emms: Setup. (line 6) * setup: Setup. (line 6) * simple player: Simple Player for `play'. (line 6) * sort: Sorting Playlists. (line 6) * Sources: Sources. (line 6) * speed: Finding files and speed. (line 6) * streaming audio: Streaming Audio. (line 6) * track editor: Editing Tracks. (line 6) * track information: Track Information. (line 6) * track order: Sorting Playlists. (line 6) * user variables: User Variables. (line 6) * Using exiftool: Using exiftool. (line 6) * using taglib: Using TagLib. (line 6) * Using tinytag: Using tinytag. (line 6) * volume: Volume. (line 6) * website: Getting Help. (line 6)  File: emms.info, Node: Function Index, Next: Variable Index, Prev: Concept Index, Up: Top Function Index ************** �[index�] * Menu: * bury-buffer: Interactive Playlists. (line 65) * define-emms-simple-player: Simple Players. (line 6) * describe-mode: Interactive Playlists. (line 73) * describe-mode <1>: Browser Interface. (line 77) * emms-add-directory: Basic Commands. (line 26) * emms-add-directory-tree: Basic Commands. (line 32) * emms-add-file: Basic Commands. (line 19) * emms-add-find: Basic Commands. (line 46) * emms-add-playlist: Basic Commands. (line 41) * emms-add-url: Basic Commands. (line 37) * emms-all: Setup. (line 17) * emms-browse-by-album: Browser Interface. (line 18) * emms-browse-by-album <1>: Browser Interface. (line 107) * emms-browse-by-artist: Browser Interface. (line 15) * emms-browse-by-artist <1>: Browser Interface. (line 104) * emms-browse-by-genre: Browser Interface. (line 21) * emms-browse-by-genre <1>: Browser Interface. (line 110) * emms-browse-by-year: Browser Interface. (line 24) * emms-browse-by-year <1>: Browser Interface. (line 113) * emms-browser-add-tracks: Browser Interface. (line 35) * emms-browser-add-tracks-and-play: Browser Interface. (line 32) * emms-browser-add-tracks-and-play <1>: Browser Interface. (line 83) * emms-browser-bury-buffer: Browser Interface. (line 62) * emms-browser-clear-playlist: Browser Interface. (line 53) * emms-browser-collapse-all: Browser Interface. (line 41) * emms-browser-expand-all: Browser Interface. (line 56) * emms-browser-expand-to-level-2: Browser Interface. (line 44) * emms-browser-expand-to-level-3: Browser Interface. (line 47) * emms-browser-expand-to-level-4: Browser Interface. (line 50) * emms-browser-goto-random: Browser Interface. (line 65) * emms-browser-lookup-album-on-pitchfork: Browser Interface. (line 116) * emms-browser-lookup-album-on-wikipedia: Browser Interface. (line 119) * emms-browser-next-filter: Browser Interface. (line 74) * emms-browser-next-non-track: Browser Interface. (line 89) * emms-browser-prev-non-track: Browser Interface. (line 86) * emms-browser-previous-filter: Browser Interface. (line 71) * emms-browser-search-by-album: Browser Interface. (line 92) * emms-browser-search-by-artist: Browser Interface. (line 95) * emms-browser-search-by-names: Browser Interface. (line 98) * emms-browser-search-by-title: Browser Interface. (line 101) * emms-browser-toggle-subitems: Browser Interface. (line 38) * emms-browser-view-in-dired: Browser Interface. (line 59) * emms-cache-set-from-mpd-all: Music Player Daemon. (line 93) * emms-cache-set-from-mpd-directory: Music Player Daemon. (line 89) * emms-cue-next: APE / FLAC Commands. (line 17) * emms-cue-previous: APE / FLAC Commands. (line 19) * emms-default-players: Setup. (line 24) * emms-history-load: Persistent Playlists. (line 21) * emms-isearch-buffer: Browser Interface. (line 68) * emms-locate: Sources. (line 48) * emms-lyrics-disable: Lyrics. (line 63) * emms-lyrics-enable: Lyrics. (line 60) * emms-lyrics-start: Lyrics. (line 48) * emms-lyrics-stop: Lyrics. (line 51) * emms-lyrics-toggle: Lyrics. (line 66) * emms-lyrics-toggle-display-on-minibuffer: Lyrics. (line 54) * emms-lyrics-toggle-display-on-modeline: Lyrics. (line 57) * emms-mark-copy-marked-tracks: Markable Playlists. (line 46) * emms-mark-delete-marked-tracks: Markable Playlists. (line 41) * emms-mark-do-with-marked-track: Markable Playlists. (line 54) * emms-mark-forward: Markable Playlists. (line 25) * emms-mark-kill-marked-tracks: Markable Playlists. (line 43) * emms-mark-mapcar-marked-track: Markable Playlists. (line 60) * emms-mark-regexp: Markable Playlists. (line 35) * emms-mark-toggle: Markable Playlists. (line 31) * emms-mark-unmark-all: Markable Playlists. (line 29) * emms-mark-unmark-forward: Markable Playlists. (line 33) * emms-metaplaylist-mode-center-current: Managing Playlists. (line 37) * emms-metaplaylist-mode-goto-current: Managing Playlists. (line 15) * emms-metaplaylist-mode-kill-buffer: Managing Playlists. (line 34) * emms-metaplaylist-mode-new-buffer: Managing Playlists. (line 31) * emms-metaplaylist-mode-set-active: Managing Playlists. (line 18) * emms-metaplaylist-mode-update: Managing Playlists. (line 28) * emms-minimalistic: Setup. (line 13) * emms-next: Basic Commands. (line 59) * emms-next <1>: Interactive Playlists. (line 38) * emms-next <2>: Interactive Playlists. (line 40) * emms-next-noerror: Core Functions. (line 11) * emms-pause: Interactive Playlists. (line 44) * emms-play-directory: Basic Commands. (line 23) * emms-play-directory-tree: Basic Commands. (line 29) * emms-play-file: Basic Commands. (line 15) * emms-play-find: Basic Commands. (line 43) * emms-play-find <1>: Sources. (line 15) * emms-play-playlist: Basic Commands. (line 39) * emms-play-url: Basic Commands. (line 35) * emms-player-for: Core Functions. (line 49) * emms-player-mpd-connect: Music Player Daemon. (line 62) * emms-player-mpd-disconnect: Music Player Daemon. (line 66) * emms-player-mpd-show: Music Player Daemon. (line 69) * emms-player-mpd-update-all: Music Player Daemon. (line 82) * emms-player-mpd-update-directory: Music Player Daemon. (line 79) * emms-player-simple-sentinel: Simple Players. (line 21) * emms-player-simple-start: Simple Players. (line 18) * emms-player-simple-stop: Simple Players. (line 16) * emms-player-start: Core Functions. (line 58) * emms-player-stop: Core Functions. (line 60) * emms-player-stopped: Core Functions. (line 62) * emms-playing-time-disable-display: Emms Mode Line. (line 35) * emms-playing-time-enable-display: Emms Mode Line. (line 32) * emms-playlist-current-selected-track: Core Functions. (line 53) * emms-playlist-limit-to-all: Limiting. (line 61) * emms-playlist-limit-to-description: Limiting. (line 31) * emms-playlist-limit-to-info-album: Limiting. (line 21) * emms-playlist-limit-to-info-artist: Limiting. (line 16) * emms-playlist-limit-to-info-composer: Limiting. (line 26) * emms-playlist-limit-to-info-genre: Limiting. (line 36) * emms-playlist-limit-to-info-performer: Limiting. (line 46) * emms-playlist-limit-to-info-title: Limiting. (line 51) * emms-playlist-limit-to-info-year: Limiting. (line 56) * emms-playlist-limit-to-name: Limiting. (line 41) * emms-playlist-mode-add-contents: Interactive Playlists. (line 32) * emms-playlist-mode-center-current: Interactive Playlists. (line 52) * emms-playlist-mode-first: Interactive Playlists. (line 59) * emms-playlist-mode-go: Interactive Playlists. (line 15) * emms-playlist-mode-insert-newline: Interactive Playlists. (line 87) * emms-playlist-mode-kill: Interactive Playlists. (line 83) * emms-playlist-mode-kill-track: Interactive Playlists. (line 78) * emms-playlist-mode-last: Interactive Playlists. (line 61) * emms-playlist-mode-play-current-track: Interactive Playlists. (line 54) * emms-playlist-mode-undo: Browser Interface. (line 80) * emms-playlist-mode-yank: Interactive Playlists. (line 81) * emms-playlist-mode-yank-pop: Interactive Playlists. (line 85) * emms-playlist-new: Playlists. (line 20) * emms-playlist-next: Core Functions. (line 17) * emms-playlist-previous: Core Functions. (line 19) * emms-playlist-save: Playlists. (line 25) * emms-playlist-save <1>: Interactive Playlists. (line 68) * emms-playlist-set-playlist-buffer: Interactive Playlists. (line 36) * emms-playlist-sort-by-file-extension: Sorting Playlists. (line 29) * emms-playlist-sort-by-file-mtime: Sorting Playlists. (line 47) * emms-playlist-sort-by-info-album: Sorting Playlists. (line 20) * emms-playlist-sort-by-info-artist: Sorting Playlists. (line 14) * emms-playlist-sort-by-info-composer: Sorting Playlists. (line 41) * emms-playlist-sort-by-info-note: Sorting Playlists. (line 38) * emms-playlist-sort-by-info-performer: Sorting Playlists. (line 32) * emms-playlist-sort-by-info-title: Sorting Playlists. (line 26) * emms-playlist-sort-by-info-year: Sorting Playlists. (line 35) * emms-playlist-sort-by-last-played: Sorting Playlists. (line 23) * emms-playlist-sort-by-name: Sorting Playlists. (line 44) * emms-playlist-sort-by-play-count: Sorting Playlists. (line 17) * emms-previous: Basic Commands. (line 61) * emms-random: Core Functions. (line 21) * emms-random <1>: Interactive Playlists. (line 63) * emms-seek: Core Functions. (line 65) * emms-seek-backward: Core Functions. (line 71) * emms-seek-backward <1>: Interactive Playlists. (line 48) * emms-seek-forward: Core Functions. (line 69) * emms-seek-forward <1>: Interactive Playlists. (line 46) * emms-show: Basic Commands. (line 68) * emms-show <1>: Interactive Playlists. (line 50) * emms-shuffle: Basic Commands. (line 63) * emms-smart-browse: Browser Interface. (line 10) * emms-sort: Basic Commands. (line 66) * emms-source-directory: Sources. (line 23) * emms-source-directory-tree: Sources. (line 26) * emms-source-dired: Sources. (line 43) * emms-source-file: Sources. (line 18) * emms-source-file-directory-tree: Sources. (line 41) * emms-source-file-regex: Sources. (line 45) * emms-source-files: Sources. (line 21) * emms-source-find: Sources. (line 38) * emms-source-playlist: Sources. (line 29) * emms-source-playlist-m3u: Sources. (line 34) * emms-source-playlist-native: Sources. (line 32) * emms-source-playlist-pls: Sources. (line 36) * emms-start: Basic Commands. (line 55) * emms-stop: Basic Commands. (line 57) * emms-stop <1>: Interactive Playlists. (line 42) * emms-tag-editor-rename: Editing Tracks. (line 89) * emms-tag-editor-replace-in-tag: Editing Tracks. (line 32) * emms-tag-editor-set-all: Editing Tracks. (line 23) * emms-tag-editor-submit: Editing Tracks. (line 47) * emms-tag-editor-transpose-tag: Editing Tracks. (line 41) * emms-toggle-random-playlist: Core Functions. (line 29) * emms-toggle-repeat-playlist: Core Functions. (line 23) * emms-toggle-repeat-track: Core Functions. (line 26) * emms-track: Core Functions. (line 35) * emms-track-description: Core Functions. (line 46) * emms-track-get: Core Functions. (line 41) * emms-track-name: Core Functions. (line 39) * emms-track-set: Core Functions. (line 44) * emms-track-type: Core Functions. (line 37) * emms-volume-lower: Volume. (line 18) * emms-volume-mode-minus: Volume. (line 29) * emms-volume-mode-plus: Volume. (line 25) * emms-volume-raise: Volume. (line 15) * kill-this-buffer: Managing Playlists. (line 40) * next-line: Managing Playlists. (line 22) * previous-line: Managing Playlists. (line 25) * scroll-up: Interactive Playlists. (line 57)  File: emms.info, Node: Variable Index, Next: Keybinding Index, Prev: Function Index, Up: Top Variable Index ************** �[index�] * Menu: * emms-history-file: Persistent Playlists. (line 14) * emms-history-start-playing: Persistent Playlists. (line 33) * emms-info-asynchronously: Track Information. (line 50) * emms-info-auto-update: Track Information. (line 46) * emms-info-functions: Track Information. (line 55) * emms-lyrics-coding-system: Lyrics. (line 36) * emms-lyrics-dir: Lyrics. (line 27) * emms-lyrics-display-format: Lyrics. (line 32) * emms-lyrics-display-on-minibuffer: Lyrics. (line 21) * emms-lyrics-display-on-modeline: Lyrics. (line 24) * emms-lyrics-scroll-p: Lyrics. (line 39) * emms-lyrics-scroll-timer-interval: Lyrics. (line 42) * emms-player-finished-hook: Hooks. (line 23) * emms-player-list: User Variables. (line 8) * emms-player-paused-hook: Hooks. (line 29) * emms-player-started-hook: Hooks. (line 9) * emms-player-stopped-hook: Hooks. (line 11) * emms-playlist-cleared-hook: Hooks. (line 19) * emms-playlist-selection-changed-hook: Hooks. (line 17) * emms-playlist-source-inserted-hook: Hooks. (line 14) * emms-repeat-playlist: User Variables. (line 15) * emms-show-format: User Variables. (line 11) * emms-sort-lessp-function: User Variables. (line 21) * emms-source-file-default-directory: Sources. (line 13) * emms-tag-editor-formats: Editing Tracks. (line 55) * emms-tag-editor-rename-format: Editing Tracks. (line 73) * emms-tag-editor-tagfile-functions: Editing Tracks. (line 63) * emms-track-description-function: User Variables. (line 19) * emms-volume-change-amount: Volume. (line 9) * emms-volume-mode-timeout: Volume. (line 42)  File: emms.info, Node: Keybinding Index, Prev: Variable Index, Up: Top Keybinding Index **************** �[index�] * Menu: * / (emms-browser): Browser Interface. (line 68) * / /: Limiting. (line 61) * / a: Limiting. (line 16) * / b: Limiting. (line 21) * / c: Limiting. (line 26) * / d: Limiting. (line 31) * / g: Limiting. (line 36) * / n: Limiting. (line 41) * / p: Limiting. (line 46) * / t: Limiting. (line 51) * / y: Limiting. (line 56) * 1 (emms-browser): Browser Interface. (line 41) * 2 (emms-browser): Browser Interface. (line 44) * 3 (emms-browser): Browser Interface. (line 47) * 4 (emms-browser): Browser Interface. (line 50) * < (emms-browser): Browser Interface. (line 71) * <backtab> (emms-browser): Browser Interface. (line 86) * <C-return> (emms-browser): Browser Interface. (line 83) * <tab> (emms-browser): Browser Interface. (line 89) * > (emms-browser): Browser Interface. (line 74) * ? (emms-browser): Browser Interface. (line 77) * b 1 (emms-browser): Browser Interface. (line 104) * b 2 (emms-browser): Browser Interface. (line 107) * b 3 (emms-browser): Browser Interface. (line 110) * b 4 (emms-browser): Browser Interface. (line 113) * C: Managing Playlists. (line 31) * c: Managing Playlists. (line 37) * C (emms-browser): Browser Interface. (line 53) * C-/ (emms-browser): Browser Interface. (line 80) * C-j (emms-browser): Browser Interface. (line 32) * C-k: Managing Playlists. (line 34) * d (emms-browser): Browser Interface. (line 59) * E (emms-browser): Browser Interface. (line 56) * g: Managing Playlists. (line 28) * n: Managing Playlists. (line 22) * p: Managing Playlists. (line 25) * q: Managing Playlists. (line 40) * q (emms-browser): Browser Interface. (line 62) * r (emms-browser): Browser Interface. (line 65) * RET: Managing Playlists. (line 15) * RET (emms-browser): Browser Interface. (line 35) * s A (emms-browser): Browser Interface. (line 92) * s a (emms-browser): Browser Interface. (line 95) * s s (emms-browser): Browser Interface. (line 98) * s t (emms-browser): Browser Interface. (line 101) * SPC: Managing Playlists. (line 18) * SPC (emms-browser): Browser Interface. (line 38) * W a p (emms-browser): Browser Interface. (line 116) * W a w (emms-browser): Browser Interface. (line 119)  Tag Table: Node: Top689 Node: Introduction4430 Node: Quickstart Guide6005 Node: Installation8755 Node: Compiling Emms9168 Node: Setup9856 Node: Configuration10842 Node: Finding files and speed12253 Node: Getting Help13099 Node: Formats and Freedom13677 Node: Basic Commands14882 Node: The Core File18263 Node: User Variables18697 Node: Hooks19673 Node: Core Functions21099 Node: Sources24099 Node: Simple Players26232 Node: Playlists27326 Node: Track Information28607 Node: Using tinytag31494 Node: Using exiftool31923 Node: Using TagLib32295 Node: Defining Info Methods33404 Node: Interactive Playlists34186 Node: Markable Playlists37228 Node: Extending Emms39699 Node: New Player40135 Node: Simple Player for `play'40524 Node: More Complex Player42252 Node: The Browser45259 Node: Browser Interface46235 Node: Filtering Tracks48649 Node: Displaying Covers50427 Node: Changing Looks52441 Node: Sorting Playlists55419 Node: Persistent Playlists56888 Node: Editing Tracks58047 Node: Emms Mode Line61721 Node: Limiting62889 Node: Music Player Daemon65228 Node: Lyrics68741 Node: Volume70789 Node: Streaming Audio72577 Ref: Streaming Audio-Footnote-173169 Node: APE / FLAC Commands73520 Node: Bookmarks74227 Node: Managing Playlists74938 Node: GNU FM75961 Node: Uploading Track Information77315 Node: GNU FM Streaming78197 Node: Copying78697 Node: The GNU FDL116214 Node: Concept Index138602 Node: Function Index143533 Node: Variable Index159225 Node: Keybinding Index161568  End Tag Table ��������������������������������������������������������������������������������������emms-6.00/jack.el�����������������������������������������������������������������������������������0000664�0001750�0001750�00000030741�13746063641�012047� 0����������������������������������������������������������������������������������������������������ustar �yrk�����������������������������yrk��������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������;;; jack.el --- Jack Audio Connection Kit support ;; Copyright (C) 2005, 2006, 2007, 2008, 2009 Free Software Foundation, Inc. ;; Author: Mario Lang <mlang@delysid.org> ;; Keywords: multimedia, processes ;; This file 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, or (at your option) ;; any later version. ;; This file 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 GNU Emacs; see the file COPYING. If not, write to ;; the Free Software Foundation, Inc., 59 Temple Place - Suite 330, ;; Boston, MA 02111-1307, USA. ;;; Commentary: ;; JACK is a low-latency audio server, written for POSIX conformant ;; operating systems such as GNU/Linux and Apple's OS X. It can connect a ;; number of different applications to an audio device, as well as ;; allowing them to share audio between themselves. Its clients can run in ;; their own processes (ie. as normal applications), or they can run ;; within the JACK server (ie. as a "plugin"). ;; ;; JACK was designed from the ground up for professional audio work, and ;; its design focuses on two key areas: synchronous execution of all ;; clients, and low latency operation. ;; ;; jack.el provides a fascility for starting jackd from within Emacs. ;; It also povides convenience functions for prompting the user for ;; jack client and port names in the minibuffer, as well as the ;; functions `jack-connect' and `jack-disconnect' which can be used to ;; rearrange jack port wiring with a minimum of keystrokes. ;;; Code: (require 'emms-compat) (defgroup jack () "Jack Audio Connection Kit" :group 'processes) (defcustom jack-rc '("~/.jackdrc" "/etc/jackd.conf") "*JACK run control paths." :group 'jack :type 'repeat) (defcustom jack-use-jack-rc t "*If non-nil, try to retrieve jack startup arguments from run control files listed in `jack-rc'. If no rc file is found or this variable is set to nil, use the Emacs variables to build the startup args." :group 'jack :type 'boolean) (defcustom jack-program (executable-find "jackd") "*JACK executable path." :group 'jack :type 'file) (defcustom jack-sample-rate 44100 "*Default sampling rate for JACK." :group 'jack :type 'integer) (defcustom jack-period-size 128 "*Period size to use when launching new JACK process." :group 'jack :type 'integer) (defcustom jack-alsa-device nil "*ALSA soundcard to use." :group 'jack :type '(choice (const :tag "Ask" nil) string)) (defun jack-read-alsa-device () "Read an ALSA device name using the minibuffer." (let (cards) (with-temp-buffer (insert-file-contents "/proc/asound/cards") (while (not (eobp)) (if (looking-at "^\\([0-9]\\) \\[.+\\]: \\(.+\\)\n +\\(.*\\)$") (setq cards (append (list (cons (match-string 3) (match-string 1))) cards))) (forward-line 1))) (concat "hw:" (cdr (assoc (completing-read "Card: " cards nil t) cards))))) (defun jack-alsa-device () (or jack-alsa-device (jack-read-alsa-device))) (defcustom jack-output-buffer-name "*JACK output*" "*Output buffer name." :group 'jack :type 'string) (defun jack-args () "Return a list of startup arguments to use. First element is the executable path." (or (and jack-use-jack-rc (catch 'rc-found (let ((files (mapcar 'expand-file-name jack-rc))) (while files (if (file-exists-p (car files)) (with-temp-buffer (insert-file-contents (car files)) (when (> (buffer-size) 0) (throw 'rc-found (split-string (buffer-string) "[\n \t]+"))))) (setq files (cdr files)))) nil)) (list jack-program "-v" "-R" "-dalsa" (format "-d%s" (jack-alsa-device)) (format "-r%d" jack-sample-rate) (format "-p%d" jack-period-size)))) (defcustom jack-set-rtlimits t "*Use set_rtlimits (if available) to gain realtime priorities if -R is given in jackd command-line." :group 'jack :type 'boolean) (defcustom jack-set-rtlimits-program (executable-find "set_rtlimits") "*Path to set_rtlimits." :group 'jack :type 'file) (defun jack-maybe-rtlimits (args) (if (and jack-set-rtlimits (or (member "-R" args) (member "--realtime" args)) (file-exists-p jack-set-rtlimits-program)) (append (list jack-set-rtlimits-program "-r") args) args)) (defvar jack-process nil) (defvar jack-load 0) (defvar jack-max-usecs 0) (defvar jack-spare 0) (defun jack-output-buffer () (or (get-buffer jack-output-buffer-name) (with-current-buffer (get-buffer-create jack-output-buffer-name) (setq major-mode 'jack-mode mode-name "JACK" mode-line-format (copy-tree mode-line-format)) (setcar (nthcdr 16 mode-line-format) `(:eval (format "load:%.2f" jack-load))) (add-hook 'kill-buffer-hook 'jack-kill nil t) (current-buffer)))) (defvar jack-xruns nil) (defun jack-filter (proc string) (with-current-buffer (process-buffer proc) (let ((moving (= (point) (process-mark proc)))) (save-excursion (save-match-data (if (string-match "^load = \\([^ ]+\\) max usecs: \\([^,]+\\), spare = \\(.+\\)$" string) (setq jack-load (string-to-number (match-string 1 string)) jack-max-usecs (string-to-number (match-string 2 string)) jack-spare (string-to-number (match-string 3 string))) (if (string-match "^**** alsa_pcm: xrun of at least \\([^ ]+\\) msecs$" string) (push (string-to-number (match-string 1 string)) jack-xruns) (goto-char (process-mark proc)) (insert string) (set-marker (process-mark proc) (point)))))) (when moving (goto-char (process-mark proc)))))) (defun jack-running-p () (and jack-process (processp jack-process) (eq (process-status jack-process) 'run))) (defcustom jack-started-hook nil "*Hook run when `jack-start' successfully started a new JACK intance." :group 'jack :type 'hook) (defun jack-start () "Start the JACK process." (interactive) (if (jack-running-p) (error "JACK already running") (setq jack-process (apply 'start-process "jack" (jack-output-buffer) (jack-maybe-rtlimits (jack-args)))) (set-process-filter jack-process #'jack-filter) (run-hooks 'jack-started-hook) (switch-to-buffer (jack-output-buffer)))) (defun jack-kill () "Kill the currently running JACK process." (interactive) (when (jack-running-p) (delete-process jack-process)) (setq jack-process nil)) (defun jack-restart () "Restart JACK." (interactive) (if (jack-running-p) (jack-kill)) (sit-for 0) (jack-start)) (defun jack-list () "Retrieve a list of JACK clients/ports." (with-temp-buffer (call-process "jack_lsp" nil t nil "-cpl") (goto-char (point-min)) (let (result current-port) (while (not (eobp)) (cond ((looking-at "^\\([^ \t:]+\\):\\(.+\\)$") (let ((program (match-string 1)) (port (match-string 2))) (if (assoc program result) (setcdr (assoc program result) (append (cdr (assoc program result)) (list (setq current-port (list port))))) (setq result (append (list (list program (setq current-port (list port)))) result))))) ((looking-at "^ \\([^ \t:]+\\):\\(.+\\)$") (if (assoc 'connections (cdr current-port)) (setcdr (assoc 'connections (cdr current-port)) (append (cdr (assoc 'connections current-port)) (list (list (match-string 1) (match-string 2))))) (setcdr current-port (append (list (list 'connections (list (match-string 1) (match-string 2)))) (cdr current-port))))) ((looking-at "^\tproperties: \\(.+\\),$") (setcdr current-port (append (list (append (list 'properties) (mapcar #'intern (split-string (match-string 1) ",")))) (cdr current-port))))) (forward-line 1)) result))) (defun jack-ports (program) (cdr (assoc program (jack-list)))) (defun jack-get-port-connections (program port) (cdr (assoc 'connections (cdr (assoc port (jack-ports program)))))) (defun jack-get-port-properties (program port) (cdr (assoc 'properties (cdr (assoc port (jack-ports program)))))) (defun jack-get-direction (program port) (let ((props (jack-get-port-properties program port))) (or (car (member 'output props)) (car (member 'input props)) (error "Neither input nor output port")))) (defun jack-read-program (prompt &optional predicate) (let ((progs (if (functionp predicate) (emms-remove-if-not predicate (jack-list)) (jack-list)))) (unless progs (error "No matching JACK clients found")) (if (< (length progs) 2) (caar progs) (completing-read prompt progs nil t)))) (defun jack-unique-port-name (strings) (let ((start "") (maxlen (apply 'min (mapcar #'length strings)))) (while (and (< (length start) maxlen) (catch 'not-ok (let ((nextchar (substring (car strings) (length start) (1+ (length start))))) (mapc (lambda (str) (unless (string= (concat start nextchar) (substring str 0 (1+ (length start)))) (throw 'not-ok nil))) strings) t))) (setq start (substring (car strings) 0 (1+ (length start))))) start)) (defun jack-read-port (program prompt &optional predicate) (let ((ports (if (functionp predicate) (emms-remove-if-not predicate (jack-ports program)) (jack-ports program)))) (if (< (length ports) 2) (caar ports) (completing-read prompt ports nil t (jack-unique-port-name (mapcar 'car ports)))))) (defun jack-connect (from-program from-port to-program to-port) "Connect FROM-PROGRAM's output port FROM-PORT to TO-PROGRAM's input port TO-PORT. If called interactively, the direction does not matter." (interactive (let* ((prog (jack-read-program "Connect: ")) (port (jack-read-port prog (format "Connect %s port: " prog))) (to-type (if (eq (jack-get-direction prog port) 'input) 'output 'input)) (to-prog (jack-read-program (format "Connect %s port %s to: " prog port) (lambda (prog) (emms-find-if (lambda (port) (member to-type (assoc 'properties (cdr port)))) (cdr prog))))) (to-port (jack-read-port to-prog (format "Connect %s port %s to %s port: " prog port to-prog) (lambda (port) (member to-type (cdr (assoc 'properties (cdr port)))))))) (if (eq to-type 'input) (list prog port to-prog to-port) (list to-prog to-port prog port)))) (let ((result (call-process "jack_connect" nil nil nil (format "%s:%s" from-program from-port) (format "%s:%s" to-program to-port)))) (if (= result 0) (message "JACK: Connected %s:%s to %s:%s" from-program from-port to-program to-port)))) (defun jack-disconnect (from-program from-port to-program to-port) "Disconnect FROM-PROGRAM's output port FROM-PORT from TO-PROGRAM's input port TO-PORT. If called interactively, the direction is not relevant." (interactive (let* ((prog (jack-read-program "Disconnect: " (lambda (prog) (emms-find-if (lambda (port) (assoc 'connections (cdr port))) (cdr prog))))) (port (jack-read-port prog (format "Disconnect %s port: " prog) (lambda (port) (assoc 'connections (cdr port))))) (connections (jack-get-port-connections prog port)) (from (list prog port)) (to (if (< (length connections) 2) (car connections) (let* ((to-progs (let (result) (mapc (lambda (conn) (if (not (member (car conn) result)) (setq result (append (list (car conn)) result)))) connections) (mapcar #'list result))) (to-prog (if (< (length to-progs) 2) (caar to-progs) (completing-read (format "Disconnect %s port %s from: " prog port) to-progs nil t)))) (setq connections (emms-remove-if-not (lambda (conn) (string= (car conn) to-prog)) connections)) (if (< (length connections) 2) (car connections) (let ((to-port (completing-read (format "Disconnect %s port %s from %s port: " prog port to-prog) (mapcar #'cdr connections) nil t))) (list to-prog to-port))))))) (if (eq (jack-get-direction prog port) 'output) (append from to) (append to from)))) (let ((result (call-process "jack_disconnect" nil nil nil (format "%s:%s" from-program from-port) (format "%s:%s" to-program to-port)))) (if (= result 0) (message "JACK: Disconnected %s:%s from %s:%s" from-program from-port to-program to-port)))) (provide 'jack) ;;; jack.el ends here �������������������������������emms-6.00/src/��������������������������������������������������������������������������������������0000775�0001750�0001750�00000000000�13746063641�011377� 5����������������������������������������������������������������������������������������������������ustar �yrk�����������������������������yrk��������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������emms-6.00/src/emms-print-metadata.c�����������������������������������������������������������������0000664�0001750�0001750�00000004401�13746063641�015413� 0����������������������������������������������������������������������������������������������������ustar �yrk�����������������������������yrk��������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������/* emms-print-metadata.c --- Info function for libtag Copyright (C) 2005, 2006, 2007, 2008, 2009 Free Software Foundation, Inc. Author: Trent Buck <trentbuck@gmail.com> 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, 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; see the file COPYING. If not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ #include <stdlib.h> #include <stdio.h> #include <tag_c.h> int main (int argc, char **argv) { TagLib_File *file; TagLib_Tag *tag; const TagLib_AudioProperties *properties; if (argc != 2) { fprintf (stderr, "usage: emms-print-metadata file.{mp3,ogg,flac}\nother formats may work as well.\n"); exit (1); } file = taglib_file_new (argv[1]); if (!file) { fprintf (stderr, "%s: File does not exist or is of an unknown type\n", argv[1]); exit (1); } tag = taglib_file_tag (file); /* Apparently, if the file is named foo.mp3 or similar, the library still can open it, for whatever reason. */ if (!tag) { fprintf (stderr, "%s: File does not exist or is of an unknown type\n", argv[1]); exit (1); } printf ("info-artist=%s\n", taglib_tag_artist (tag)); printf ("info-title=%s\n", taglib_tag_title (tag)); printf ("info-album=%s\n", taglib_tag_album (tag)); printf ("info-tracknumber=%d\n", taglib_tag_track (tag)); printf ("info-year=%d\n", taglib_tag_year (tag)); printf ("info-genre=%s\n", taglib_tag_genre (tag)); printf ("info-note=%s\n", taglib_tag_comment (tag)); properties = taglib_file_audioproperties (file); printf ("info-playing-time=%d\n", properties ? taglib_audioproperties_length (properties) : 0); taglib_tag_free_strings (); taglib_file_free (file); return 0; } /* emms-print-metadata.c ends here. */ ���������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������emms-6.00/src/emms-print-metadata.cpp���������������������������������������������������������������0000664�0001750�0001750�00000005523�13746063641�015761� 0����������������������������������������������������������������������������������������������������ustar �yrk�����������������������������yrk��������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������/* emms-print-metadata.cpp --- Info function for TagLib Copyright (C) 2016 Free Software Foundation, Inc. Author: Petteri Hintsanen <petterih@iki.fi> 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, 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; see the file COPYING. If not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ #include <taglib/fileref.h> #include <taglib/tag.h> #include <taglib/tpropertymap.h> #include <iostream> static const char* const tags_to_extract[] = { "album", "albumsort", "albumartist", "albumartistsort", "artist", "artistsort", "composer", "composersort", "performer", "year", "originalyear", "date", "originaldate", "genre", "label", "title", "titlesort", "tracknumber", "discnumber" }; void print_tag (const TagLib::PropertyMap& tags, const std::string& tag); int main (int argc, char* argv[]) { if (argc != 2) { std::cerr << argv[0] << ": " << "usage: emms-print-metadata FILENAME" << std::endl << "FILENAME must end to one of these extensions: " << TagLib::FileRef::defaultFileExtensions ().toString () << std::endl; return 1; } TagLib::FileRef file (argv[1]); if (file.isNull ()) { std::cerr << argv[0] << ": " << argv[1] << ": " << "file does not exist or is of an unknown type" << std::endl; return 1; } const TagLib::PropertyMap tags = file.file ()->properties (); if (tags.isEmpty ()) { std::cerr << argv[0] << ": " << argv[1] << ": " << "file does not have tags or is of an unknown type" << std::endl; return 1; } for (unsigned int i = 0; i < sizeof (tags_to_extract) / sizeof (char*); i++) { print_tag (tags, tags_to_extract[i]); } int length = 0; if (file.audioProperties ()) { const TagLib::AudioProperties* properties = file.audioProperties (); length = properties->length (); } std::cout << "info-playing-time=" << length << std::endl; return 0; } void print_tag (const TagLib::PropertyMap& tags, const std::string& tag) { TagLib::StringList values = tags[tag]; if (!values.isEmpty ()) { const TagLib::String& value = values.front (); std::cout << "info-" << tag << "=" << value.to8Bit (true) << std::endl; } } /* emms-print-taglib-metadata.cpp ends here. */ �����������������������������������������������������������������������������������������������������������������������������������������������������������������������������emms-6.00/src/emms-print-metadata.pl����������������������������������������������������������������0000775�0001750�0001750�00000006245�13746063641�015617� 0����������������������������������������������������������������������������������������������������ustar �yrk�����������������������������yrk��������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������#!/usr/bin/perl # emms-print-metadata.pl --- Info function for libtag # Copyright (C) 2012 Free Software Foundation, Inc. # Author: Lucas Bonnet <lbonnet@rincevent.net> # 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, 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; see the file COPYING. If not, write to # the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, # Boston, MA 02110-1301, USA. use strict; use warnings; use Audio::Scan; use File::Basename; # enable UTF-8 output binmode(STDOUT, ":utf8"); my $file = $ARGV[0]; # Scan without reading (possibly large) artwork into memory. # Instead of binary artwork data, the size of the artwork will be returned instead. local $ENV{AUDIO_SCAN_NO_ARTWORK} = 1; my $data = Audio::Scan->scan($file); # determines the names of tags according to file type my %ext_map = ("mp3" => {'artist' => 'TPE1', 'title' => 'TIT2', 'album' => 'TALB', 'tracknumber' => 'TRCK', 'composer' => 'TCOM', 'performer' => 'TPE2', 'year' => 'TDRC', 'genre' => 'TCON', 'comment' => 'COMM'}, "flc" => {'artist' => 'ARTIST', 'title' => 'TITLE', 'album' => 'ALBUM', 'tracknumber' => 'TRACKNUMBER', 'composer' => 'COMPOSER', 'performer' => 'PERFORMER', 'year' => 'DATE', 'genre' => 'GENRE', 'comment' => 'COMMENT'}, "ogg" => {'artist' => 'ARTIST', 'title' => 'TITLE', 'album' => 'ALBUM', 'tracknumber' => 'TRACKNUMBER', 'composer' => 'COMPOSER', 'performer' => 'PERFORMER', 'year' => 'DATE', 'genre' => 'GENRE', 'comment' => 'COMMENT'}, ); # find out extension my ($filename, $directories, $extension) = fileparse($file, qr/[^.]*/); my $type = Audio::Scan->type_for(lc($extension)); my $tag_map = $ext_map{$type}; # print tag info print "info-artist="; safe_print('artist'); print "info-title="; safe_print('title'); print "info-album="; safe_print('album'); print "info-tracknumber="; safe_print('tracknumber'); print "info-composer="; safe_print('composer'); print "info-performer="; safe_print('performer'); print "info-year="; safe_print('year'); print "info-genre="; safe_print('genre'); print "info-note=" ; safe_print('comment'); print "info-playing-time=",int($data->{'info'}->{'song_length_ms'} / 1000),"\n"; sub safe_print { my $k = shift; if (defined $data->{'tags'}->{ $tag_map->{$k} }) { print $data->{'tags'}->{ $tag_map->{$k} }; } else { print "<no $k>"; } print "\n"; } �����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������emms-6.00/emms-auto.el������������������������������������������������������������������������������0000664�0001750�0001750�00000045745�13746064010�013047� 0����������������������������������������������������������������������������������������������������ustar �yrk�����������������������������yrk��������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������;;; -*-emacs-lisp-*- (defvar generated-autoload-file) (defvar command-line-args-left) (defun emms-generate-autoloads () (interactive) (require 'autoload) (setq generated-autoload-file (car command-line-args-left)) (setq command-line-args-left (cdr command-line-args-left)) (batch-update-autoloads)) (add-to-list 'load-path (directory-file-name (or (file-name-directory load-file-name) (car load-path)))) (provide 'emms-auto) ;;; Generated autoloads follow (made by autoload.el). ;;;### (autoloads nil "emms" "emms.el" (0 0 0 0)) ;;; Generated autoloads from emms.el (if (fboundp 'register-definition-prefixes) (register-definition-prefixes "emms" '("define-emms-" "emms-" "with-current-emms-playlist"))) ;;;*** ;;;### (autoloads nil "emms-browser" "emms-browser.el" (0 0 0 0)) ;;; Generated autoloads from emms-browser.el (autoload 'emms-browser "emms-browser" "\ Launch or switch to the EMMS Browser." t nil) (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." t nil) (if (fboundp 'register-definition-prefixes) (register-definition-prefixes "emms-browser" '("case-fold-string" "emms-"))) ;;;*** ;;;### (autoloads nil "emms-cache" "emms-cache.el" (0 0 0 0)) ;;; Generated autoloads from emms-cache.el (autoload 'emms-cache-enable "emms-cache" "\ Enable caching of Emms track data." t nil) (autoload 'emms-cache-disable "emms-cache" "\ Disable caching of Emms track data." t nil) (autoload 'emms-cache-toggle "emms-cache" "\ Toggle caching of Emms track data." t nil) (if (fboundp 'register-definition-prefixes) (register-definition-prefixes "emms-cache" '("emms-cache"))) ;;;*** ;;;### (autoloads nil "emms-compat" "emms-compat.el" (0 0 0 0)) ;;; Generated autoloads from emms-compat.el (if (fboundp 'register-definition-prefixes) (register-definition-prefixes "emms-compat" '("emms-"))) ;;;*** ;;;### (autoloads nil "emms-cue" "emms-cue.el" (0 0 0 0)) ;;; Generated autoloads from emms-cue.el (if (fboundp 'register-definition-prefixes) (register-definition-prefixes "emms-cue" '("emms-"))) ;;;*** ;;;### (autoloads nil "emms-history" "emms-history.el" (0 0 0 0)) ;;; Generated autoloads from emms-history.el (if (fboundp 'register-definition-prefixes) (register-definition-prefixes "emms-history" '("emms-history-"))) ;;;*** ;;;### (autoloads nil "emms-i18n" "emms-i18n.el" (0 0 0 0)) ;;; Generated autoloads from emms-i18n.el (if (fboundp 'register-definition-prefixes) (register-definition-prefixes "emms-i18n" '("emms-i18n-"))) ;;;*** ;;;### (autoloads nil "emms-info" "emms-info.el" (0 0 0 0)) ;;; Generated autoloads from emms-info.el (if (fboundp 'register-definition-prefixes) (register-definition-prefixes "emms-info" '("emms-info-"))) ;;;*** ;;;### (autoloads nil "emms-info-exiftool" "emms-info-exiftool.el" ;;;;;; (0 0 0 0)) ;;; Generated autoloads from emms-info-exiftool.el (if (fboundp 'register-definition-prefixes) (register-definition-prefixes "emms-info-exiftool" '("emms-info-exiftool"))) ;;;*** ;;;### (autoloads nil "emms-info-libtag" "emms-info-libtag.el" (0 ;;;;;; 0 0 0)) ;;; Generated autoloads from emms-info-libtag.el (if (fboundp 'register-definition-prefixes) (register-definition-prefixes "emms-info-libtag" '("emms-info-libtag"))) ;;;*** ;;;### (autoloads nil "emms-info-metaflac" "emms-info-metaflac.el" ;;;;;; (0 0 0 0)) ;;; Generated autoloads from emms-info-metaflac.el (if (fboundp 'register-definition-prefixes) (register-definition-prefixes "emms-info-metaflac" '("emms-info-metaflac"))) ;;;*** ;;;### (autoloads nil "emms-info-mp3info" "emms-info-mp3info.el" ;;;;;; (0 0 0 0)) ;;; Generated autoloads from emms-info-mp3info.el (if (fboundp 'register-definition-prefixes) (register-definition-prefixes "emms-info-mp3info" '("emms-info-mp3"))) ;;;*** ;;;### (autoloads nil "emms-info-ogginfo" "emms-info-ogginfo.el" ;;;;;; (0 0 0 0)) ;;; Generated autoloads from emms-info-ogginfo.el (if (fboundp 'register-definition-prefixes) (register-definition-prefixes "emms-info-ogginfo" '("emms-info-ogginfo"))) ;;;*** ;;;### (autoloads nil "emms-info-opusinfo" "emms-info-opusinfo.el" ;;;;;; (0 0 0 0)) ;;; Generated autoloads from emms-info-opusinfo.el (if (fboundp 'register-definition-prefixes) (register-definition-prefixes "emms-info-opusinfo" '("emms-info-opusinfo"))) ;;;*** ;;;### (autoloads nil "emms-info-tinytag" "emms-info-tinytag.el" ;;;;;; (0 0 0 0)) ;;; Generated autoloads from emms-info-tinytag.el (if (fboundp 'register-definition-prefixes) (register-definition-prefixes "emms-info-tinytag" '("emms-info-tinytag"))) ;;;*** ;;;### (autoloads nil "emms-last-played" "emms-last-played.el" (0 ;;;;;; 0 0 0)) ;;; Generated autoloads from emms-last-played.el (if (fboundp 'register-definition-prefixes) (register-definition-prefixes "emms-last-played" '("emms-last-played-"))) ;;;*** ;;;### (autoloads nil "emms-later-do" "emms-later-do.el" (0 0 0 0)) ;;; Generated autoloads from emms-later-do.el (if (fboundp 'register-definition-prefixes) (register-definition-prefixes "emms-later-do" '("emms-later-do"))) ;;;*** ;;;### (autoloads nil "emms-librefm-scrobbler" "emms-librefm-scrobbler.el" ;;;;;; (0 0 0 0)) ;;; Generated autoloads from emms-librefm-scrobbler.el (if (fboundp 'register-definition-prefixes) (register-definition-prefixes "emms-librefm-scrobbler" '("emms-librefm-scrobbler-"))) ;;;*** ;;;### (autoloads nil "emms-librefm-stream" "emms-librefm-stream.el" ;;;;;; (0 0 0 0)) ;;; Generated autoloads from emms-librefm-stream.el (if (fboundp 'register-definition-prefixes) (register-definition-prefixes "emms-librefm-stream" '("emms-librefm-stream"))) ;;;*** ;;;### (autoloads nil "emms-lyrics" "emms-lyrics.el" (0 0 0 0)) ;;; Generated autoloads from emms-lyrics.el (autoload 'emms-lyrics-enable "emms-lyrics" "\ Enable displaying emms lyrics." t nil) (autoload 'emms-lyrics-disable "emms-lyrics" "\ Disable displaying emms lyrics." t nil) (autoload 'emms-lyrics-toggle "emms-lyrics" "\ Toggle displaying emms lyrics." t nil) (if (fboundp 'register-definition-prefixes) (register-definition-prefixes "emms-lyrics" '("emms-lyrics"))) ;;;*** ;;;### (autoloads nil "emms-mark" "emms-mark.el" (0 0 0 0)) ;;; Generated autoloads from emms-mark.el (if (fboundp 'register-definition-prefixes) (register-definition-prefixes "emms-mark" '("emms-mark-"))) ;;;*** ;;;### (autoloads nil "emms-metaplaylist-mode" "emms-metaplaylist-mode.el" ;;;;;; (0 0 0 0)) ;;; Generated autoloads from emms-metaplaylist-mode.el (if (fboundp 'register-definition-prefixes) (register-definition-prefixes "emms-metaplaylist-mode" '("emms-metaplaylist-mode"))) ;;;*** ;;;### (autoloads nil "emms-mode-line" "emms-mode-line.el" (0 0 0 ;;;;;; 0)) ;;; Generated autoloads from emms-mode-line.el (autoload 'emms-mode-line-enable "emms-mode-line" "\ Turn on `emms-mode-line'." t nil) (autoload 'emms-mode-line-disable "emms-mode-line" "\ Turn off `emms-mode-line'." t nil) (autoload 'emms-mode-line-toggle "emms-mode-line" "\ Toggle `emms-mode-line'." t nil) (if (fboundp 'register-definition-prefixes) (register-definition-prefixes "emms-mode-line" '("emms-mode-line"))) ;;;*** ;;;### (autoloads nil "emms-mode-line-icon" "emms-mode-line-icon.el" ;;;;;; (0 0 0 0)) ;;; Generated autoloads from emms-mode-line-icon.el (if (fboundp 'register-definition-prefixes) (register-definition-prefixes "emms-mode-line-icon" '("emms-mode-line-icon-"))) ;;;*** ;;;### (autoloads nil "emms-player-mpd" "emms-player-mpd.el" (0 0 ;;;;;; 0 0)) ;;; Generated autoloads from emms-player-mpd.el (autoload 'emms-player-mpd-clear "emms-player-mpd" "\ Clear the MusicPD playlist." t nil) (autoload 'emms-player-mpd-connect "emms-player-mpd" "\ Connect to MusicPD and retrieve its current playlist. Afterward, the status of MusicPD will be tracked. This also has the effect of changing the current EMMS playlist to be the same as the current MusicPD playlist. Thus, this function is useful to call if the contents of the EMMS playlist buffer get out-of-sync for some reason." t nil) (autoload 'emms-player-mpd-show "emms-player-mpd" "\ Describe the current EMMS track in the minibuffer. If INSERTP is non-nil, insert the description into the current buffer instead. If CALLBACK is a function, call it with the current buffer and description as arguments instead of displaying the description or inserting it. This function uses `emms-show-format' to format the current track. It differs from `emms-show' in that it asks MusicPD for the current track, rather than EMMS. \(fn &optional INSERTP CALLBACK)" t nil) (if (fboundp 'register-definition-prefixes) (register-definition-prefixes "emms-player-mpd" '("emms-"))) ;;;*** ;;;### (autoloads nil "emms-player-mpg321-remote" "emms-player-mpg321-remote.el" ;;;;;; (0 0 0 0)) ;;; Generated autoloads from emms-player-mpg321-remote.el (if (fboundp 'register-definition-prefixes) (register-definition-prefixes "emms-player-mpg321-remote" '("emms-player-mpg321-remote"))) ;;;*** ;;;### (autoloads nil "emms-player-mplayer" "emms-player-mplayer.el" ;;;;;; (0 0 0 0)) ;;; Generated autoloads from emms-player-mplayer.el (if (fboundp 'register-definition-prefixes) (register-definition-prefixes "emms-player-mplayer" '("emms-player-mplayer-" "mplayer"))) ;;;*** ;;;### (autoloads nil "emms-player-mpv" "emms-player-mpv.el" (0 0 ;;;;;; 0 0)) ;;; Generated autoloads from emms-player-mpv.el (if (fboundp 'register-definition-prefixes) (register-definition-prefixes "emms-player-mpv" '("emms-player-mpv"))) ;;;*** ;;;### (autoloads nil "emms-player-simple" "emms-player-simple.el" ;;;;;; (0 0 0 0)) ;;; Generated autoloads from emms-player-simple.el (if (fboundp 'register-definition-prefixes) (register-definition-prefixes "emms-player-simple" '("alsaplayer" "define-emms-simple-player" "emms-player-" "fluidsynth" "mikmod" "mpg321" "ogg123" "playsound" "speexdec" "timidity"))) ;;;*** ;;;### (autoloads nil "emms-player-vlc" "emms-player-vlc.el" (0 0 ;;;;;; 0 0)) ;;; Generated autoloads from emms-player-vlc.el (if (fboundp 'register-definition-prefixes) (register-definition-prefixes "emms-player-vlc" '("emms-player-vlc-" "vlc"))) ;;;*** ;;;### (autoloads nil "emms-player-xine" "emms-player-xine.el" (0 ;;;;;; 0 0 0)) ;;; Generated autoloads from emms-player-xine.el (if (fboundp 'register-definition-prefixes) (register-definition-prefixes "emms-player-xine" '("emms-" "xine"))) ;;;*** ;;;### (autoloads nil "emms-playing-time" "emms-playing-time.el" ;;;;;; (0 0 0 0)) ;;; Generated autoloads from emms-playing-time.el (autoload 'emms-playing-time-enable-display "emms-playing-time" "\ Display playing time on mode line." t nil) (autoload 'emms-playing-time-disable-display "emms-playing-time" "\ Remove playing time from mode line." t nil) (if (fboundp 'register-definition-prefixes) (register-definition-prefixes "emms-playing-time" '("emms-playing-time"))) ;;;*** ;;;### (autoloads nil "emms-playlist-limit" "emms-playlist-limit.el" ;;;;;; (0 0 0 0)) ;;; Generated autoloads from emms-playlist-limit.el (if (fboundp 'register-definition-prefixes) (register-definition-prefixes "emms-playlist-limit" '("define-emms-playlist-limit" "emms-playlist-limit-"))) ;;;*** ;;;### (autoloads nil "emms-playlist-mode" "emms-playlist-mode.el" ;;;;;; (0 0 0 0)) ;;; Generated autoloads from emms-playlist-mode.el (autoload 'emms-playlist-mode "emms-playlist-mode" "\ A major mode for Emms playlists. \\{emms-playlist-mode-map}" t nil) (if (fboundp 'register-definition-prefixes) (register-definition-prefixes "emms-playlist-mode" '("emms"))) ;;;*** ;;;### (autoloads nil "emms-playlist-sort" "emms-playlist-sort.el" ;;;;;; (0 0 0 0)) ;;; Generated autoloads from emms-playlist-sort.el (if (fboundp 'register-definition-prefixes) (register-definition-prefixes "emms-playlist-sort" '("define-emms-playlist-sort" "emms-"))) ;;;*** ;;;### (autoloads nil "emms-score" "emms-score.el" (0 0 0 0)) ;;; Generated autoloads from emms-score.el (autoload 'emms-score-enable "emms-score" "\ Turn on emms-score." t nil) (autoload 'emms-score-disable "emms-score" "\ Turn off emms-score." t nil) (autoload 'emms-score-toggle "emms-score" "\ Toggle emms-score." t nil) (if (fboundp 'register-definition-prefixes) (register-definition-prefixes "emms-score" '("emms-score"))) ;;;*** ;;;### (autoloads nil "emms-setup" "emms-setup.el" (0 0 0 0)) ;;; Generated autoloads from emms-setup.el (autoload 'emms-minimalistic "emms-setup" "\ An Emms setup script. Invisible playlists and all the basics for playing media." nil nil) (autoload 'emms-all "emms-setup" "\ An Emms setup script. Everything included in the `emms-minimalistic' setup and adds all the stable features which come with the Emms distribution." nil nil) (autoload 'emms-default-players "emms-setup" "\ Set `emms-player-list' to `emms-setup-default-player-list'." nil nil) (autoload 'emms-devel "emms-setup" nil nil nil) (autoload 'emms-standard "emms-setup" nil nil nil) (if (fboundp 'register-definition-prefixes) (register-definition-prefixes "emms-setup" '("emms-setup-default-player-list"))) ;;;*** ;;;### (autoloads nil "emms-show-all" "emms-show-all.el" (0 0 0 0)) ;;; Generated autoloads from emms-show-all.el (if (fboundp 'register-definition-prefixes) (register-definition-prefixes "emms-show-all" '("emms-show-all"))) ;;;*** ;;;### (autoloads nil "emms-source-file" "emms-source-file.el" (0 ;;;;;; 0 0 0)) ;;; 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) (autoload 'emms-play-directory "emms-source-file" nil t) (autoload 'emms-add-directory "emms-source-file" nil t) (autoload 'emms-play-directory-tree "emms-source-file" nil t) (autoload 'emms-add-directory-tree "emms-source-file" nil t) (autoload 'emms-play-find "emms-source-file" nil t) (autoload 'emms-add-find "emms-source-file" nil t) (autoload 'emms-play-dired "emms-source-file" nil t) (autoload 'emms-add-dired "emms-source-file" nil t) (autoload 'emms-source-file-directory-tree "emms-source-file" "\ Return a list of all files under DIR that match REGEX. This function uses `emms-source-file-directory-tree-function'. \(fn DIR REGEX)" nil nil) (autoload 'emms-source-file-regex "emms-source-file" "\ Return a regexp that matches everything any player (that supports files) can play." nil nil) (autoload 'emms-locate "emms-source-file" "\ Search for REGEXP and display the results in a locate buffer \(fn REGEXP)" t nil) (autoload 'emms-play-url "emms-source-file" nil t) (autoload 'emms-add-url "emms-source-file" nil t) (autoload 'emms-play-streamlist "emms-source-file" nil t) (autoload 'emms-add-streamlist "emms-source-file" nil t) (if (fboundp 'register-definition-prefixes) (register-definition-prefixes "emms-source-file" '("dire" "emms-" "file" "find" "streamlist" "url"))) ;;;*** ;;;### (autoloads nil "emms-source-playlist" "emms-source-playlist.el" ;;;;;; (0 0 0 0)) ;;; Generated autoloads from emms-source-playlist.el (autoload 'emms-play-playlist "emms-source-playlist" nil t) (autoload 'emms-add-playlist "emms-source-playlist" nil t) (autoload 'emms-play-native-playlist "emms-source-playlist" nil t) (autoload 'emms-add-native-playlist "emms-source-playlist" nil t) (autoload 'emms-play-m3u-playlist "emms-source-playlist" nil t) (autoload 'emms-add-m3u-playlist "emms-source-playlist" nil t) (autoload 'emms-play-pls-playlist "emms-source-playlist" nil t) (autoload 'emms-add-pls-playlist "emms-source-playlist" nil t) (autoload 'emms-play-playlist-file "emms-source-playlist" nil t) (autoload 'emms-add-playlist-file "emms-source-playlist" nil t) (autoload 'emms-play-playlist-directory "emms-source-playlist" nil t) (autoload 'emms-add-playlist-directory "emms-source-playlist" nil t) (autoload 'emms-play-playlist-directory-tree "emms-source-playlist" nil t) (autoload 'emms-add-playlist-directory-tree "emms-source-file" nil t) (if (fboundp 'register-definition-prefixes) (register-definition-prefixes "emms-source-playlist" '("emms-" "m3u-playlist" "native-playlist" "playlist" "pls-playlist"))) ;;;*** ;;;### (autoloads nil "emms-streams" "emms-streams.el" (0 0 0 0)) ;;; Generated autoloads from emms-streams.el (if (fboundp 'register-definition-prefixes) (register-definition-prefixes "emms-streams" '("emms-streams"))) ;;;*** ;;;### (autoloads nil "emms-tag-editor" "emms-tag-editor.el" (0 0 ;;;;;; 0 0)) ;;; Generated autoloads from emms-tag-editor.el (if (fboundp 'register-definition-prefixes) (register-definition-prefixes "emms-tag-editor" '("emms-tag-editor-"))) ;;;*** ;;;### (autoloads nil "emms-url" "emms-url.el" (0 0 0 0)) ;;; Generated autoloads from emms-url.el (if (fboundp 'register-definition-prefixes) (register-definition-prefixes "emms-url" '("emms-"))) ;;;*** ;;;### (autoloads nil "emms-volume" "emms-volume.el" (0 0 0 0)) ;;; Generated autoloads from emms-volume.el (autoload 'emms-volume-raise "emms-volume" "\ Raise the speaker volume." t nil) (autoload 'emms-volume-lower "emms-volume" "\ Lower the speaker volume." t nil) (autoload 'emms-volume-mode-plus "emms-volume" "\ Raise volume and enable or extend the `emms-volume-minor-mode' timeout." t nil) (autoload 'emms-volume-mode-minus "emms-volume" "\ Lower volume and enable or extend the `emms-volume-minor-mode' timeout." t nil) (if (fboundp 'register-definition-prefixes) (register-definition-prefixes "emms-volume" '("emms-volume-"))) ;;;*** ;;;### (autoloads nil "emms-volume-amixer" "emms-volume-amixer.el" ;;;;;; (0 0 0 0)) ;;; Generated autoloads from emms-volume-amixer.el (autoload 'emms-volume-amixer-change "emms-volume-amixer" "\ Change amixer master volume by AMOUNT. \(fn AMOUNT)" nil nil) (if (fboundp 'register-definition-prefixes) (register-definition-prefixes "emms-volume-amixer" '("emms-volume-amixer-c"))) ;;;*** ;;;### (autoloads nil "emms-volume-mixerctl" "emms-volume-mixerctl.el" ;;;;;; (0 0 0 0)) ;;; Generated autoloads from emms-volume-mixerctl.el (autoload 'emms-volume-mixerctl-change "emms-volume-mixerctl" "\ Change mixerctl master volume by AMOUNT. \(fn AMOUNT)" nil nil) (if (fboundp 'register-definition-prefixes) (register-definition-prefixes "emms-volume-mixerctl" '("emms-volume-mixerctl-c"))) ;;;*** ;;;### (autoloads nil "emms-volume-pulse" "emms-volume-pulse.el" ;;;;;; (0 0 0 0)) ;;; Generated autoloads from emms-volume-pulse.el (autoload 'emms-volume-pulse-change "emms-volume-pulse" "\ Change PulseAudio volume by AMOUNT. \(fn AMOUNT)" nil nil) (if (fboundp 'register-definition-prefixes) (register-definition-prefixes "emms-volume-pulse" '("emms-volume-"))) ;;;*** ;;;### (autoloads nil "jack" "jack.el" (0 0 0 0)) ;;; Generated autoloads from jack.el (if (fboundp 'register-definition-prefixes) (register-definition-prefixes "jack" '("jack-"))) ;;;*** ;;;### (autoloads nil nil ("emms-maint.el" "emms-stream-info.el") ;;;;;; (0 0 0 0)) ;;;*** ;;;### (autoloads nil "emms-bookmarks" "emms-bookmarks.el" (0 0 0 ;;;;;; 0)) ;;; Generated autoloads from emms-bookmarks.el (if (fboundp 'register-definition-prefixes) (register-definition-prefixes "emms-bookmarks" '("emms-bookmarks-"))) ;;;*** ���������������������������emms-6.00/ChangeLog���������������������������������������������������������������������������������0000664�0001750�0001750�00001301260�13746064010�012354� 0����������������������������������������������������������������������������������������������������ustar �yrk�����������������������������yrk��������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������commit 6fad47928d78f652669563216a7d939ad4c1c104 Author: Yoni Rabkin <yoni@rabkins.net> Date: Tue Oct 27 14:32:01 2020 -0400 update NEWS and version bump commit 52dc0bd21de846db17e20a02d072603338ae33d7 Author: Yoni Rabkin <yoni@rabkins.net> Date: Fri Sep 25 10:53:23 2020 -0400 * doc/emms.texinfo: commit eafd962556c7786ad8b070845c9e332641dae960 Author: Yoni Rabkin <yoni@rabkins.net> Date: Thu Sep 24 22:14:11 2020 -0400 * emms-setup.el: add exiftool commit 53944e11a9ac6acb92d53157315530757a4b3ae7 Author: Yoni Rabkin <yoni@rabkins.net> Date: Thu Sep 24 21:04:06 2020 -0400 * doc/emms.texinfo: update manual regarding exiftool commit e7298ee8e42aad33ba555028bb52f78ab31ad776 Author: Yoni Rabkin <yoni@rabkins.net> Date: Thu Sep 24 15:31:22 2020 -0400 * emms-info-exiftool.el: new info method commit eff3777e104f00f62357068d4e41c58dd0b0585c Author: Yoni Rabkin <yoni@rabkins.net> Date: Tue Sep 22 17:23:26 2020 -0400 * emms.el: version bump commit feee374521617e9852641889d0fc5d5909bf3f11 Author: Yoni Rabkin <yoni@rabkins.net> Date: Tue Sep 22 17:21:15 2020 -0400 * emms-later-do.el: name change Conver later-do to emms-later-do in order not to pollute the namespace. commit e2891f2740f54b31c1a6741dda6df5c0be1f3be6 Author: Yoni Rabkin <yoni@rabkins.net> Date: Tue Sep 22 17:11:37 2020 -0400 * doc/developer-release.txt: elpa notes commit 36d760e2bd7e5376aff3f03456fa6445833242ad Author: Bruno Félix Rezende Ribeiro <oitofelix@gnu.org> Date: Thu Jul 16 15:10:33 2020 -0300 * emms-volume.el: Fix missing quote in emms-volume-change-function This change was originally commited in b136d63, but somehow got lost. It’s critical because otherwise EMMS volume library won’t load on systems lacking ‘amixer’ and ‘pactl’. commit 699895f68a202ae0d497ed1155039db64768adc3 Author: Yoni Rabkin <yoni@rabkins.net> Date: Fri Jun 12 17:00:07 2020 -0400 * NEWS: update news commit 40e6fdf5f8da2aec73c2767b576e1799996bb34f Author: Yoni Rabkin <yoni@rabkins.net> Date: Fri Jun 12 16:58:33 2020 -0400 version bump for elpa commit be35f11af8b4dad7266f4c031c6d8d636535d874 Author: Yoni Rabkin <yoni@rabkins.net> Date: Fri Jun 12 16:55:34 2020 -0400 Add emms.info to top-level for elpa to find. commit 1a67c30c186145de7cd950411151b883b1b6838e Author: Yoni Rabkin <yoni@rabkins.net> Date: Thu Jun 11 14:02:21 2020 -0400 * emms-auto.el: remove erroneously added file This file will be generated. commit 5dbffa6292765f52b6e3d776e243b5340a3de607 Author: Yoni Rabkin <yoni@rabkins.net> Date: Tue Jun 9 13:44:12 2020 -0400 * emms-auto.el: add emms-auto commit 9aa6c191d925670e65defecdb9db8364a78c83af Author: Yoni Rabkin <yoni@rabkins.net> Date: Tue Jun 9 13:42:28 2020 -0400 * .gitignore: update commit e102891fb3bbb3fec134b5c678a0dd2306b9beaf Author: Yoni Rabkin <yoni@rabkins.net> Date: Wed Jun 3 11:52:04 2020 -0400 move all files to top-level commit f177bf33cd8dac05908b19ae2c5c33ffbb5eeacf Author: Yoni Rabkin <yoni@rabkins.net> Date: Tue Jun 2 09:51:33 2020 -0400 Copyright format updates for elpa inclusion commit 7e3d548b9ba12501aa43637e468856ac4be0bc16 Author: Yoni Rabkin <yoni@rabkins.net> Date: Fri May 29 16:37:00 2020 -0400 * lisp/emms-auto.in: make elpa load aware of lisp/ commit fb00718c526f96405da020721ceec2d4fcae1190 Author: Yoni Rabkin <yoni@rabkins.net> Date: Fri May 29 13:38:08 2020 -0400 * emms.el: interface to elpa Yes, it unfortunately carries the same name as lisp/emms.el commit 3eed06dde4c683bb5f2f43a65a554900445351a0 Author: Yoni Rabkin <yoni@rabkins.net> Date: Thu May 28 17:16:44 2020 -0400 More elpa work. Unfortunately, this commit is more of a "one step forward, two steps back" kind of situation. commit ecdac97e8a2aed88d37380daccc594e2bb54b7d8 Author: Yoni Rabkin <yoni@rabkins.net> Date: Wed May 27 15:40:42 2020 -0400 * emms-elpa.el: experiment with elpa integration commit 59cc585cfad3c2f666006e4b1c049dfa676fffd4 Author: Yoni Rabkin <yoni@rabkins.net> Date: Wed May 27 11:18:32 2020 -0400 * Makefile: generate a dir info file commit 27bf18f4f138503f67151c2ad31d07cee3dccbb8 Author: Yoni Rabkin <yoni@rabkins.net> Date: Wed May 27 10:58:56 2020 -0400 * lisp/emms.el: add elpa appropriate headers commit 64b9ee9c86067118b2d0055f467e60bc211aa59d Author: Yoni Rabkin <yoni@rabkins.net> Date: Fri May 8 15:55:55 2020 -0400 * doc/emms.texinfo: document tinytag interface commit b192eb5d52e655a827d9d96879aaa85d71f17187 Author: Yoni Rabkin <yoni@rabkins.net> Date: Fri May 8 15:22:19 2020 -0400 * lisp/emms-info-tinytag.el: commit 71d4e468c543f7f7ea33617bf94556e43c0f34ed Author: Fran Burstall <fran.burstall@gmail.com> Date: Fri May 8 11:13:13 2020 +0100 * lisp/emms-info-tinytag.el: info source using tinytag commit f4924c2e77bdc5806495a74832fba60b2c30aca1 Author: Yoni Rabkin <yoni@rabkins.net> Date: Fri May 1 11:23:03 2020 -0400 Updates for version bump. commit 2767c660562d35f02f9b272252a697804d70dd14 Author: Yoni Rabkin <yoni@rabkins.net> Date: Wed Feb 12 13:25:31 2020 -0500 * lisp/emms-streams.el: fix type commit 615c73ee970dd4ffcca2541bfa9e6e884ddddde3 Author: Yoni Rabkin <yoni@rabkins.net> Date: Wed Feb 12 13:24:20 2020 -0500 * lisp/emms-streams.el: Added WXHQ-LP radio Added WXHQ-LP radio station for consideration. commit f941e28a6767a32a6e716b44ea86ef33156aed1b Author: Yoni Rabkin <yoni@rabkins.net> Date: Mon Jan 20 09:38:58 2020 -0500 * NEWS: commit 6acae6e170a6bd13034eacf6d091331bdc0d0ed2 Author: Bruno Félix Rezende Ribeiro <oitofelix@oitofelix.com> Date: Sat Jan 18 13:20:19 2020 -0300 * lisp/emms-volume.el: add ‘Mixerctl’ to custom interface Affects user option ‘emms-volume-change-function’. commit 1f15a81d458c05585b58341be24568df790a40bc Author: Yoni Rabkin <yoni@rabkins.net> Date: Thu Jan 16 13:44:48 2020 -0500 * lisp/emms-stream-info.el: remove old code commit 8a355a4451eb39a214a4c4441ec652cfd53dc37d Author: Yoni Rabkin <yoni@rabkins.net> Date: Thu Jan 16 13:33:26 2020 -0500 * lisp/emms-streams.el: fix compilation warnings commit 3cf79f88bcb5204ca74d0e576780f535d96f5bf2 Author: Yoni Rabkin <yoni@rabkins.net> Date: Wed Jan 15 16:07:02 2020 -0500 * lisp/emms-source-file.el: guess the directory Try to guess the directory if the adding a file is called over a 'file type track-at-point. commit eedd61d9639de043933293b662a148d57d2f8a2f Author: Mike Kazantsev <mk.fraggod@gmail.com> Date: Fri Dec 6 03:26:58 2019 +0500 * lisp/emms-player-mpv.el: fix skipping track when switching them during playback with mpv-0.30 commit ae5ba1eac8edd0b46725c2f392a46b521075a8b1 Author: Yoni Rabkin <yoni@rabkins.net> Date: Fri Nov 15 14:13:54 2019 -0500 * lisp/emms-streams.el: update built-in streams list commit 735bfde5cc7a0727bce2a9657d7d7cf2b957bba7 Author: Yoni Rabkin <yoni@rabkins.net> Date: Wed Nov 6 14:41:07 2019 -0500 * NEWS: commit 248d427c2a7fef829fea8de6e0f659b4b04b595e Author: Yoni Rabkin <yoni@rabkins.net> Date: Wed Nov 6 14:33:17 2019 -0500 * doc/emms.texinfo: document streaming commit 101b91e2ff4985de47550fcd972767cb15e5fb6c Author: Yoni Rabkin <yoni@rabkins.net> Date: Wed Nov 6 13:37:16 2019 -0500 * lisp/emms-streams.el: complete rewrite commit 342ffff018657b3984c7d57cc509540c0b0670c1 Author: Yoni Rabkin <yoni@rabkins.net> Date: Wed Nov 6 13:36:55 2019 -0500 * lisp/emms-source-playlist.el: replace with variable commit 96b80680cc4c1306efb7ad65382138989e506910 Author: Yoni Rabkin <yoni@rabkins.net> Date: Fri Nov 1 10:16:01 2019 -0400 * Makefile: fix comment commit a8075b52fa75c5b53892214e6ca89fe0b42a04bf Author: Yoni Rabkin <yoni@rabkins.net> Date: Fri Nov 1 09:55:10 2019 -0400 Bump to 5.3. commit 6dfc9ffbfc91d333f1e2d4ada821e243eb868726 Author: Yoni Rabkin <yoni@rabkins.net> Date: Thu Sep 5 17:07:30 2019 -0400 * lisp/emms-volume.el: small bug fix Thank you to Jordan Wilson for catching this. commit b136d63c252aa9e9a09fcee561fe86c4aab92f20 Author: Bruno Félix Rezende Ribeiro <oitofelix@gnu.org> Date: Mon Sep 2 23:12:19 2019 -0300 * lisp/emms-volume.el: Fix missing quote in emms-volume-change-function commit aa3357403153100484561cb7235fffc3faccfb00 Author: Mike Kazantsev <mk.fraggod@gmail.com> Date: Tue Sep 3 01:07:37 2019 +0500 * lisp/emms-player-mpv.el: limit emacs issue #3190 workaround to emacs 26.1 (fixed in 26.2+) commit f209b44c76f4a8532783909384ae7492b8d9b6e7 Author: Yoni Rabkin <yoni@rabkins.net> Date: Tue Aug 27 12:10:01 2019 -0400 emms-volume auto-detection commit 16ae09fa2e45306d71337099e524bdbe29ebb792 Author: Yoni Rabkin <yoni@rabkins.net> Date: Mon Aug 26 12:44:35 2019 -0400 * lisp/emms-volume-mixerctl.el: new file Thanks to Bruno Félix Rezende Ribeiro; new contributor (assignment papers sent as of writing.) commit e70459caaadeb715116abb45ddf5e98921d46c14 Author: Yoni Rabkin <yoni@rabkins.net> Date: Thu Jun 20 11:26:27 2019 -0400 * lisp/emms-playing-time.el: fix time display commit d913726a127ecd8f956f02be785f258f042aa384 Author: Yoni Rabkin <yoni@rabkins.net> Date: Wed Jun 19 13:28:12 2019 -0400 * lisp/emms-playing-time.el: add count-down style. commit f7e27094f09432b40ced77c7163cd29f338b7db6 Author: Yoni Rabkin <yoni@rabkins.net> Date: Wed May 29 13:11:46 2019 -0400 * lisp/emms-source-playlist.el: make less surprising Will now warn if the current playlist buffer isn't the one being visited, instead of silently saving the current playlist buffer. commit 2253146e5607e12f62b0c1c474fded1219da2d5d Author: Yoni Rabkin <yoni@rabkins.net> Date: Wed May 1 12:39:59 2019 -0400 Bump to version 5.2. commit 6013464eb7295fcd749b3146f758fc9295fbe11a Author: Pierre Neidhardt <mail@ambrevar.xyz> Date: Thu Feb 21 17:46:58 2019 +0100 * lisp/emms-browser.el: Add emms-browser-cache-thumbnail-async for faster thumbnail lookups. commit 4eed4ce2f8105245617e5e529077c5a6635e45f8 Author: Yoni Rabkin <yoni@rabkins.net> Date: Wed Feb 6 10:37:35 2019 -0500 * lisp/emms-player-mpd.el: set tracknumber. From: Emanuel Evans <mail@emanuel.industries> Subject: [emms-help] [PATCH] Parse disc number for mpd tracks (1 line patch) commit 58666af620067dfcef2dd491dfd8f08c8decbe0e Author: Yoni Rabkin <yoni@rabkins.net> Date: Mon Feb 4 11:31:20 2019 -0500 * lisp/emms-source-playlist.el: thing-at-point fix Jordan Wilson <jordan.t.wilson@gmx.com>'s thing-at-point fixes. commit e5763d23106177de1ab75a51400de312bce4d7c8 Author: Yoni Rabkin <yoni@rabkins.net> Date: Wed Jan 9 10:02:30 2019 -0500 * lisp/emms-playlist-mode.el: Remove redundancy. `emms-playlist-mode-clear' is redundant and nobody calls it, so it is removed. commit bb451d9f5392cc45202ed8e742abf2b1ac55ecd0 Author: Yoni Rabkin <yoni@rabkins.net> Date: Wed Jan 9 09:49:36 2019 -0500 * lisp/emms.el: Fix doc string. commit de5643494ae61617aa247b00d42d84b84ea9b12e Author: Yoni Rabkin <yoni@rabkins.net> Date: Fri Jan 4 16:12:40 2019 -0500 * lisp/emms-mode-line-icon.el: allow changing icon Allow the icon's color to be changed easily. commit 52c5080f2ee8d9c499ab12a3ba5b2b5585f5063c Author: Yoni Rabkin <yoni@rabkins.net> Date: Fri Jan 4 12:53:00 2019 -0500 * lisp/emms-playlist-mode.el: behavior as docstring Bug report from Carlos (thank you) that the behavior of the function didn't follow the docstring. commit 359e1d38d09060b5f7860320649d6c30b71e4bbe Author: Fran Burstall <fran.burstall@gmail.com> Date: Thu Nov 22 19:32:42 2018 +0000 * lisp/emms-browser.el: bug fix Don't rely on (interactive "r"): it can error out if no mark ever set. commit 56d9ec27dbbe75496e338f6621e196c04472470f Author: Yoni Rabkin <yoni@rabkins.net> Date: Thu Nov 1 14:19:12 2018 -0400 * Makefile: bump to 5.1 commit 47b1054683f4fa0a1ecd9999cb94c5c34994e018 Author: Yoni Rabkin <yoni@rabkins.net> Date: Thu Nov 1 14:13:35 2018 -0400 * lisp/emms.el: bump to 5.1 commit 8eb1037e9b02b0a6e141d8c51612cbb9398afcf6 Author: Yoni Rabkin <yoni@rabkins.net> Date: Mon Oct 29 11:14:10 2018 -0400 * NEWS: update. commit e5d5385e75e50e6cf1e2d5c9d1e4966f478b5319 Author: Yoni Rabkin <yoni@rabkins.net> Date: Mon Oct 22 09:23:05 2018 -0400 * lisp/emms-playlist-limit.el: bug fix Fix discrepancy between emacs 26.x and 25.x in handling the format arguments. commit dfc2d4fd611054468b08f744d6b05f7e5cbc3877 Author: Fran Burstall <fran.burstall@gmail.com> Date: Sat Oct 20 10:12:51 2018 +0100 * lisp/emms-mark.el: Correct prompt in emms-mark-regexp commit 4437c84ee2b0b328255c5c417705fbef4c8906fc Author: Fran Burstall <fran.burstall@gmail.com> Date: Wed Oct 17 21:18:23 2018 +0100 * lisp/emms-streams.el: add doc-string to emms-stream-mode So that describe-mode shows the keymap. commit 1b81dbf1ebc1d50ae3791d228bb9a07b5c03445d Author: Yoni Rabkin <yoni@rabkins.net> Date: Wed Oct 17 16:12:22 2018 -0400 * NEWS: commit c31006f83af6b3bb87f444581ddde38b331199da Author: Fran Burstall <fran.burstall@gmail.com> Date: Wed Oct 17 21:02:50 2018 +0100 * lisp/emms-playlist-sort.el: sort current buffer Sort the playlist in the current buffer rather than emms-current-playlist commit 955b15cef78872b55625b0fc32798c569ec7615b Author: Yoni Rabkin <yoni@rabkins.net> Date: Wed Oct 17 15:51:23 2018 -0400 * lisp/emms-streams.el: add Rinse FM commit 5742eb170490049a67f0e238f219ccb65054d1c5 Author: Fran Burstall <fran.burstall@gmail.com> Date: Mon Oct 8 21:26:57 2018 +0100 * doc/emms.texinfo: further document emms-playlist-limit commit c15a2d24ef537768d5d4295d7950f3600d9f0361 Author: Fran Burstall <fran.burstall@gmail.com> Date: Sun Oct 7 23:18:59 2018 +0100 * lisp/emms-metaplaylist-mode.el: describe-mode shows keymap commit 838bb9f73fc7ea895ed08a1785aeb3dd6f7b98bb Author: Fran Burstall <feb@maths.bath.ac.uk> Date: Sun Oct 7 20:43:15 2018 +0100 * NEWS: update commit 83503e6b276bf2382c8d0d1975d5b0e4dc8eacef Author: Fran Burstall <feb@maths.bath.ac.uk> Date: Sat Oct 6 09:08:21 2018 +0100 * lisp/emms-playlist-limit.el: fix up whitespace. commit 23ea5748244c8f2794e2d90a7ed564e2a326ec5a Author: Fran Burstall <feb@maths.bath.ac.uk> Date: Fri Oct 5 23:53:58 2018 +0100 * lisp/emms-playlist-limit.el: limit by track description commit 67c49998da1812b50f645d255898c1fc40d2a10a Author: Yoni Rabkin <yoni@rabkins.net> Date: Fri Oct 5 14:47:21 2018 -0400 * lisp/emms.el: default to emms-playlist-mode commit 8d35c26cd6f5cfd4ec97ee5bc274e931809f4094 Author: Fran Burstall <feb@maths.bath.ac.uk> Date: Thu Sep 27 23:15:22 2018 +0100 * NEWS: update commit 776a08b4897b63f802cbdb27d6fc79de8238def4 Author: Yoni Rabkin <yoni@rabkins.net> Date: Thu Sep 27 13:36:55 2018 -0400 * lisp/emms-playlist-limit.el: fix copyright commit 111ba19004e39c0efb50c9e9021706587564ac22 Author: Fran Burstall <feb@maths.bath.ac.uk> Date: Wed Sep 26 23:39:11 2018 +0100 * lisp/emms-playlist-limit.el: operate on current buffer Instead of the current playlist. commit acbd7af54e907f0fb4aeb199883491176dbfa35b Author: Fran Burstall <feb@maths.bath.ac.uk> Date: Tue Sep 25 23:27:17 2018 +0100 * lisp/emms-playlist-limit.el: recycle derived playlist commit 309babf7af4a05faae2a1d91dcad94812e99a3db Author: Yoni Rabkin <yoni@rabkins.net> Date: Tue Sep 25 14:21:54 2018 -0400 * doc/emms.texinfo: document emms-playlist-limit commit f9b2e8214790a89b22952cfa6b33c2de88f8e145 Author: Fran Burstall <feb@maths.bath.ac.uk> Date: Tue Sep 25 18:27:23 2018 +0100 AUTHORS: add author commit 0b0fcb6d4c1bc68e403d28cdf96fc704538d4a9c Author: Fran Burstall <feb@maths.bath.ac.uk> Date: Tue Sep 25 18:27:07 2018 +0100 NEWS: update commit 51266993f5de3dec88ae3486d22ce40a72ab3ba4 Author: Fran Burstall <feb@maths.bath.ac.uk> Date: Mon Sep 24 20:07:23 2018 +0100 lisp/emms-setup.el: remove explicit emms-playlist-limit activation emms-playlist-limit only needs to be required as it no longer sets any hooks commit f3d622108048c2470797f4cfb77e67db9f72fd3c Author: Fran Burstall <feb@maths.bath.ac.uk> Date: Mon Sep 24 20:03:37 2018 +0100 lisp/emms-playlist-limit.el: major re-write Builds new playlist without killing the old one. Various bugs squashed along the way. commit 18bf3ec10d8e37323a91c08f67acfe033a31055d Author: Fran Burstall <feb@maths.bath.ac.uk> Date: Mon Sep 24 19:54:12 2018 +0100 lisp/emms-playlist-limit.el: Update top matter, add commentary * Did I get the copyright line right? commit 6583d31e94e6b71b88f547966ed8bba9e6ea993b Author: Yoni Rabkin <yoni@rabkins.net> Date: Fri Sep 7 16:59:09 2018 -0400 * lisp/emms-playlist-mode.el: avoid mistypes Make killing the current playlist buffer by a mistype harder. commit a43047f6a298632b875971aeb16bd529f0dfed33 Author: Pierre Neidhardt <ambrevar@gmail.com> Date: Mon Aug 27 10:31:43 2018 +0200 * AUTHORS: Update email address commit 9b702f38e3486d67cb67194e98ea72dda25be1af Author: Yoni Rabkin <yoni@rabkins.net> Date: Sun Jul 8 21:23:54 2018 -0400 * lisp/emms.el: add `emms-ok-track-function' Add `emms-ok-track-function', which is a simpler way of controlling if Emms would skip a particular track. commit 4cc4dd97c40f4275f1e4aba0ac5964feb1a7e278 Author: Yoni Rabkin <yoni@rabkins.net> Date: Sun Jul 8 21:23:09 2018 -0400 * lisp/emms-score.el: Use `emms-ok-track-function' Simplify and correct the way emms-score skips tracks. commit e91b00ef19c2078d41deeec041150e61b0d0f0fa Author: Yoni Rabkin <yoni@rabkins.net> Date: Sun Jul 8 21:02:44 2018 -0400 * lisp/emms.el: add single-track mode Add a buffer-local option of playing a single track and then stopping. commit ae1e9834c874dcb471847e6a34367d0b22c6be62 Author: Mike Kazantsev <mk.fraggod@gmail.com> Date: Mon Jul 2 14:57:48 2018 +0500 * lisp/emms-player-mpv.el: fix emacs-26 ipc issue #3190 workaround check commit f5a09d93c86c676cbce490cf670f95e6fe127c9f Author: Mike Kazantsev <mk.fraggod@gmail.com> Date: Sat Jun 30 21:45:49 2018 +0500 * lisp/emms-player-mpv.el: use blocking ipc sockets as a workaround for emacs-26 issue #31901 Workaround is used for all future emacs versions, until known-working release will be available. It can be bad for performance if mpv becomes unresponsive. commit b0b406189b96ba9b0773e1c40449a0f0c9abf95e Author: Mike Kazantsev <mk.fraggod@gmail.com> Date: Sat Jun 30 20:08:33 2018 +0500 * lisp/emms-player-mpv.el: make sure socket directory exists for all ipc types commit 45ee4c54ea4311533c764d7b617b845394c82ae4 Author: Yoni Rabkin <yoni@rabkins.net> Date: Wed Jun 27 08:04:27 2018 -0400 * lisp/emms-player-mpv.el: ensure mpv socket Make sure directory for mpv socket exists (Daniel Kraus) commit 9f9a9b81f741692f2d188d1b46e72f2b6db8a9a1 Author: Yoni Rabkin <yoni@rabkins.net> Date: Tue Jun 26 11:36:44 2018 -0400 * lisp/emms-player-mpv.el: change ipc file location Daniel Kraus writes in with a one line fix: "Don't litter mpv ipc files in the users emacs home directory but put it it emms folder where all other emms related files are." commit 94d26e10954765e079bde3c98d67ccb535b4c3a7 Author: Yoni Rabkin <yoni@rabkins.net> Date: Wed Jun 20 16:22:13 2018 -0400 * lisp/emms-history.el: bug fix `emms-history-load' -> /a -> // would empty the buffer One line patch by Fran Burstall. commit ab3012ebc5da166ef242b8ebd63de53b738c4f96 Author: Yoni Rabkin <yoni@rabkins.net> Date: Mon Jun 18 12:17:22 2018 -0400 * lisp/emms-playlist-limit.el: make buffer local commit 95df1c69c6a7b2c8085115d651cf90756cc338a1 Author: Yoni Rabkin <yoni@rabkins.net> Date: Wed Jun 13 23:43:50 2018 -0400 * lisp/emms-show-all.el: bug fix: bad behavior Fix quitting the window so that it behaves well. Bug report by Fran Burstall. commit 536fd3307c2004b0d6da55a818a4977e822e109f Author: Yoni Rabkin <yoni@rabkins.net> Date: Wed Jun 13 23:33:36 2018 -0400 * lisp/emms-show-all.el: bug fix: preempted defvar Buffer read-only error on keymap interaction. Bug report by Fran Burstall. commit 3b608a5499f1151111029ba8a9cbcec4fcae46ef Author: Mike Kazantsev <mk.fraggod@gmail.com> Date: Wed Jun 6 19:11:19 2018 +0500 * lisp/emms-player-mpv.el: use shell-quote-argument instead of ad-hoc escaping in emms-player-mpv-ipc-connect-fifo commit a23ee71cd1340f34bb57ab713d86dbf5d19aeaae Author: Mike Kazantsev <mk.fraggod@gmail.com> Date: Wed Jun 6 19:07:51 2018 +0500 * lisp/emms-player-mpv.el: reset emms-player-mpv-proc after initial interrupt/delete This is to avoid leaving unreferenced process alive when execution is interrupted via C-g or SIGUSR2. commit c70124a0bc28027f98ccea103a0d89340898d71f Author: Pierre Neidhardt <ambrevar@gmail.com> Date: Wed Jun 6 13:47:07 2018 +0200 * lisp/emms-player-mpv.el: Use capitals and imperative form in docstrings commit 377bc595f51cedb0717bfe9fbe3da11db166fb09 Author: Pierre Neidhardt <ambrevar@gmail.com> Date: Wed Jun 6 13:46:23 2018 +0200 * lisp/emms-player-mpv.el: Replace hex #xa with the more explicit ?\n commit aefee6ddae1f50811921792ef8d0de8af5e4df89 Author: Pierre Neidhardt <ambrevar@gmail.com> Date: Wed Jun 6 13:45:48 2018 +0200 * lisp/emms-player-mpv.el: Replace (if ... nil) with (and ...) commit 16c7a42ffea8285ae6af2d70d023ac5af7db93df Author: Yoni Rabkin <yoni@rabkins.net> Date: Mon May 28 11:02:53 2018 -0400 * lisp/emms-player-mpv.el: indentation commit 0386cf5dc13da5170c94d60ff1619f75df19d16e Author: Mike Kazantsev <mk.fraggod@gmail.com> Date: Mon May 28 17:27:24 2018 +0500 * lisp/emms-player-mpv: change sexp formatting style to be more in-line with rest of the code commit 9dbe771bf188bc404de4fc2dad77b1f8cba9cfb6 Author: Mike Kazantsev <mk.fraggod@gmail.com> Date: Mon May 28 08:20:52 2018 +0500 * lisp/emms-player-mpv: add emms-player-base-format-list regexp for emms-add-* functions to use commit fdf8ede86113f62211a7d873b19b19698464e003 Author: Mike Kazantsev <mk.fraggod@gmail.com> Date: Mon May 28 08:19:11 2018 +0500 * lisp/emms-player-mpv: use emms-player-mpv- prefix and sharp-quotes consistently commit c22c53e043cb431a572ceb406885bfbb9da09046 Author: Yoni Rabkin <yoni@rabkins.net> Date: Sun May 27 22:20:50 2018 -0400 * lisp/emms-metaplaylist-mode.el: bug fix Metalplaylist buffer focus would error without a current buffer. commit 9e3e94526175359da902529fd60de00ab2a538ea Author: Mike Kazantsev <mk.fraggod@gmail.com> Date: Sat May 26 03:16:08 2018 +0500 * lisp/emms-player-mpv: fix playback state tracking for --input-file processes commit 015a10ed8ed31d629bef34a10a4d77519bcfa356 Author: Mike Kazantsev <mk.fraggod@gmail.com> Date: Sat May 26 02:13:14 2018 +0500 * NEWS: fix one minor tab/space mixup commit 55c83369162231b31433cd404466e5641cd90353 Author: Mike Kazantsev <mk.fraggod@gmail.com> Date: Sat May 26 02:02:04 2018 +0500 * lisp/emms-player-mpv.el: full rewrite with added json-rpc support Rewritten from scratch, supporting both old oneshot mpv process operation as well as long-running mpv --idle instances for newer versions. commit 40acbffce2d0a5341651df3495b1ccdf4832420f Author: Pierre Neidhardt <ambrevar@gmail.com> Date: Thu May 17 18:22:25 2018 +0200 * lisp/emms-browser.el: Prioritize albumartist and artist over the sort tags commit cffef39bd9297154b3ed91a68f8fc230e0f87fba Author: Yoni Rabkin <yoni@rabkins.net> Date: Tue May 1 14:43:15 2018 -0400 bump to version 5.0 commit 6740042df600637032dd71794f1b600a85c4099d Author: ZHANG Weiyi <dochang@gmail.com> 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 <yoni@rabkins.net> Date: Thu Apr 12 09:43:51 2018 -0400 * NEWS: commit e69e910843594a09d8e337b7724ae2e67cc73f84 Author: Yoni Rabkin <yoni@rabkins.net> 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 <ambrevar@gmail.com> Date: Tue Apr 10 09:51:16 2018 +0530 * NEWS: update commit 9ca1984fac4843635d512da20243c1556e194ec6 Author: Pierre Neidhardt <ambrevar@gmail.com> 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 <yoni@rabkins.net> 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 <ambrevar@gmail.com> 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 <ambrevar@gmail.com> 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 <ambrevar@gmail.com> 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 <ambrevar@gmail.com> 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 <ambrevar@gmail.com> 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 <ambrevar@gmail.com> 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 <ambrevar@gmail.com> 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 <ambrevar@gmail.com> 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 <ambrevar@gmail.com> 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 <return> to add a sequence of tracks. commit 26908fa4ec7725027c996d10373a61e00ff1b935 Author: Pierre Neidhardt <ambrevar@gmail.com> 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 <yoni@rabkins.net> Date: Mon Apr 9 10:35:27 2018 -0400 * NEWS: update Update the latest of Pierre's work. commit a0b351d0572bfe264e23aa3ef8c660be354252e7 Author: Yoni Rabkin <yoni@rabkins.net> 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 <ambrevar@gmail.com> 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 <ambrevar@gmail.com> Date: Mon Apr 9 11:49:26 2018 +0530 * lisp/emms-player-mpv.el: Add the mpv backend commit 58c83cf6c640bc241fb933ce743d1876bbcbba8c Author: Pierre Neidhardt <ambrevar@gmail.com> 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 <yoni@rabkins.net> Date: Thu Apr 5 16:59:06 2018 -0400 * AUTHORS: minor fix commit 84ca32a8562162c3e6001ba54acba139f2023435 Author: Yoni Rabkin <yoni@rabkins.net> Date: Tue Apr 3 10:49:11 2018 -0400 * NEWS: reword commit ffd8c0e8a7649d4e3a0d4f9d65e114346145a2de Author: Yoni Rabkin <yoni@rabkins.net> Date: Wed Mar 28 10:58:37 2018 -0400 * NEWS: shout out to Pierre commit cf361f15912ba27e26cda2796f28aa128cd5a970 Author: Yoni Rabkin <yoni@rabkins.net> Date: Wed Mar 28 10:56:35 2018 -0400 * NEWS: update commit 51fd0927372c63833b998b86174b920def3b172a Author: Yoni Rabkin <yoni@rabkins.net> Date: Wed Mar 28 10:53:48 2018 -0400 * doc/emms.texinfo: mention mid3v2 commit e94ed1cff1513f536c920ed3076319a1021d8842 Author: Yoni Rabkin <yoni@rabkins.net> Date: Wed Mar 28 10:50:49 2018 -0400 * lisp/emms-tag-editor.el: depreciate mp3info commit 7a5da34e1192dd7a32545a7c0edbd9bb69e7922e Author: Yoni Rabkin <yoni@rabkins.net> 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 <ambrevar@gmail.com> Date: Sat Feb 17 21:19:35 2018 +0100 Set emms-directory according to user-emacs-directory commit 3a8d16d91edae81ffb2bb9efa12d41712edfd4f8 Author: Pierre Neidhardt <ambrevar@gmail.com> Date: Wed Jan 3 14:20:50 2018 +0100 Obsolete emms-devel and emms-all commit f586070b598b1a19842212686e88df346f1ebc1f Author: Pierre Neidhardt <ambrevar@gmail.com> Date: Fri Dec 29 22:04:34 2017 +0100 Define all mode-maps with defvar instead of defconst commit 1ba1707f398b541baee516a9314b1ae1cc2f5bae Author: Pierre Neidhardt <ambrevar@gmail.com> Date: Fri Dec 29 22:01:32 2017 +0100 emms-browser: Add mode hook commit 5650f6bbcd05e9759193342a3004af4de252765c Author: Yoni Rabkin <yoni@rabkins.net> 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 <ambrevar@gmail.com> Date: Tue Dec 26 10:13:32 2017 +0100 Add Homepage to the package header commit de28c9389f1d347e2d6ee7329d6fcb3aac274a28 Author: Yoni Rabkin <yoni@rabkins.net> Date: Fri Dec 15 18:05:41 2017 -0500 * NEWS: update commit 1aa7b6581fa1a99bcd9ee4187a2522033847f64c Author: Yoni Rabkin <yoni@rabkins.net> 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 <yoni@rabkins.net> 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 <yoni@rabkins.net> 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 <ambrevar@gmail.com> Date: Sat Dec 9 16:44:24 2017 +0100 Fix 'seq' requirement in emms-browser commit bcad17702f4aea763491efb62551f3f5888cc0b2 Author: Pierre Neidhardt <ambrevar@gmail.com> Date: Sat Dec 9 16:30:49 2017 +0100 AUTHORS: Add Pierre Neidhardt commit e70461dd1a1ad09c92a4d1753f94e95abc76eeb2 Author: Pierre Neidhardt <ambrevar@gmail.com> Date: Sat Dec 9 16:30:01 2017 +0100 Document dynamic cover thumbnail caching commit d4a75dda9316dfe8ec9dfe7368b226121ad5e898 Author: Pierre Neidhardt <ambrevar@gmail.com> 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 <ambrevar@gmail.com> Date: Sun Dec 3 20:01:28 2017 +0100 Add support for dynamic thumbnail caching commit 0960515e644015c6d85549fa3bef3d67c0ee7116 Author: Pierre Neidhardt <ambrevar@gmail.com> 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 <ambrevar@gmail.com> 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 <yoni@rabkins.net> 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 <yoni@rabkins.net> 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 <yoni@rabkins.net> Date: Sun Nov 5 08:02:16 2017 -0500 Push version updates. commit 88fecd0234da595843ce6be4d3f9f2b755ff612d Author: Yoni Rabkin <yoni@rabkins.net> Date: Fri Oct 20 16:49:00 2017 -0400 * lisp/emms-player-mpd.el: allow socket Allow mpd to read directly from a named socket. commit 175e5af5250503c12a395f5559923d2b9367aae3 Author: Yoni Rabkin <yoni@rabkins.net> Date: Wed Oct 11 15:02:21 2017 -0400 * NEWS: update commit 25b2dc242028076cd1d6c011b509133ae193af7e Author: Yoni Rabkin <yoni@rabkins.net> Date: Wed Oct 11 14:58:31 2017 -0400 * lisp/emms-volume-amixer.el: card choice Add an option to specify the card amixer will control. commit b1ea89a08da3f5953d55072fffed8f781b461315 Author: Yoni Rabkin <yoni@rabkins.net> Date: Fri Sep 29 17:27:50 2017 -0400 * lisp/emms.el: set-playlist-buffer bugfix Take into account destructive sorting. Patch thanks to Ian Dunn. commit 881bfaef42e58e04822d944a51ccad0efb9ab7be Author: Yoni Rabkin <yoni@rabkins.net> Date: Wed Sep 13 16:07:56 2017 -0400 * lisp/emms-source-file.el: follow symlinks Emms-source-file-directory-tree-find now follows symlinks. Thank you Maxim Cournoyer for the patch. commit 79793c0bb32620ad5b4db490c6e80ff8e5a20233 Author: Yoni Rabkin <yoni@rabkins.net> Date: Fri Sep 1 16:30:52 2017 -0400 update NEWS commit de1ff3252b3113a1e622cd3d63b65479cc474525 Author: Yoni Rabkin <yoni@rabkins.net> Date: Fri Sep 1 16:28:14 2017 -0400 * doc/emms.texinfo: update documentation Update the `emms-playlist-sort' documentation. commit 93b4340e6fd2b34f50aec2fa129e3d4122f6a5f6 Author: Yoni Rabkin <yoni@rabkins.net> Date: Fri Sep 1 16:27:37 2017 -0400 * lisp/emms-playlist-sort.el: new function Sort playlist by file mtime. commit e790730a4e258440184bc8ce5d3015efe09f8984 Author: Yoni Rabkin <yoni@rabkins.net> Date: Sat Jul 15 12:07:04 2017 -0400 * lisp/emms.el: add package-requires commit 1335277ece54bd0cffd71c36843c228f99b41b30 Author: Yoni Rabkin <yoni@rabkins.net> Date: Fri Jul 14 16:21:07 2017 -0400 * NEWS: update commit 5401b0df9b4a45fb9f01b7f4236f99b34c79595a Author: Yoni Rabkin <yoni@rabkins.net> Date: Fri Jul 14 16:16:21 2017 -0400 Move from cl to cl-lib. Patch by tumashu <tumashu@163.com>. commit a4ec6697e45a006753bfd79c22f14524748df493 Author: Yoni Rabkin <yoni@rabkins.net> Date: Mon Jun 19 14:58:56 2017 -0400 * AUTHORS: add trivial patch author commit a6aa6ca703336ab3fd26f25f36c45894d8ecea5f Author: Yoni Rabkin <yoni@rabkins.net> Date: Mon Jun 19 14:56:40 2017 -0400 * lisp/emms-volume.el: fix typo trivial patch by David Michael <fedora.dm0@gmail.com> commit 0ebffc0b7263d261c9de1f117a96d28447889dfd Author: Yoni Rabkin <yoni@rabkins.net> Date: Mon Jun 19 14:55:40 2017 -0400 * lisp/emms-volume.el: Limits volume percentages Limits volume percentages between 0 and 100 by default. At least with the Solaris sink, attempting to set a volume outside this range will fail with a "connection terminated" error from pactl. trivial patch by David Michael <fedora.dm0@gmail.com> commit 0481ca3b8f8d558e545582440dde6dac514818fe Author: Yoni Rabkin <yoni@rabkins.net> Date: Thu Jun 1 19:51:38 2017 -0400 * lisp/emms-player-mpg321-remote.el: fix signal This fixes auto playing not working. Seems @P3 is the new mpg321 signal for song being over, so both P0 and P3 should be checked. SRC: https://www.apt-browse.org/browse/debian/wheezy/main/i386/mpg321/0.3.2-1.1/file/usr/share/doc/mpg321/README.remote Patch (trivial) from <pintolo1234@gmail.com> commit 179e8e73f501115a9b0c73056846d80809d5a144 Author: Yoni Rabkin <yoni@rabkins.net> Date: Mon May 1 14:52:04 2017 -0400 * doc/developer-release.txt: comment commit 4cb3ae341847e8e8586373a95a458a453469812d Author: Yoni Rabkin <yoni@rabkins.net> Date: Mon May 1 14:02:58 2017 -0400 Bump version to 4.3. commit 946e954e78013f19fed870b16935aa0865c5cae7 Author: Yoni Rabkin <yoni@rabkins.net> Date: Mon Apr 17 16:46:54 2017 -0400 * NEWS: commit 6acda00f9d428516be4e8d407aefd51838f9395b Author: Yoni Rabkin <yoni@rabkins.net> Date: Mon Apr 17 16:44:48 2017 -0400 * lisp/emms-browser.el: Cover only on info album. Get the cover only when the album info is requested. Small patch by Cedric Chepied <cedric.chepied@gmail.com>. commit 0cd9ea411391c9049f4fbcd5d9164ba11b73fe56 Author: Yoni Rabkin <yoni@rabkins.net> Date: Mon Apr 17 10:02:59 2017 -0400 * doc/developer-release.txt: correct text This would avoid a previous tag being pushed and clobbering HEAD. commit 6e795ce6117322ae5dd8a4b3e2f4ff073495ba5d Author: Yoni Rabkin <yoni@rabkins.net> Date: Mon Apr 17 09:49:39 2017 -0400 * doc/developer-release.txt: Add tags comment. commit 6601ba8ef710b8ed260773e18a3baa940a7adc3a Author: Yoni Rabkin <yoni@rabkins.net> Date: Wed Mar 1 17:06:42 2017 -0500 Move to a new emms-print-metadata. The new emms-print-metadata is written in C++ and brings on board new features from TagLib. Patch by Petteri Hintsanen <petterih@iki.fi>. commit 0b0bdd12eb97797d3c481de70871d64f42672a58 Author: Yoni Rabkin <yoni@rabkins.net> Date: Sun Feb 26 17:29:51 2017 -0500 * lisp/emms-player-mpd.el: Remove obsolete Replace the obsolete function with its up-to-date equivalent. commit c3d98fc234cf7ec751c78a63a467449ccfd74376 Author: Rasmus <rasmus@gmx.us> Date: Wed Dec 21 14:32:44 2016 +0100 * lisp/emms-lyrics.el (emms-lyrics-visit-lyric): Fix error from 6bc5 commit dde22abffb7a47adfe2cf98e4505ac0048e0b5fd Author: Yoni Rabkin <yrk@gnu.org> Date: Thu Dec 22 17:46:36 2016 -0500 * lisp/emms-streams.el: replace obsolete function. `toggle-read-only' is obsolete. Use `read-only-mode' instead. commit 1a2df61904b4d35a1c098fa0d11573b8ca61036e Author: Yoni Rabkin <yoni@rabkins.net> Date: Wed Dec 21 07:59:25 2016 -0500 * doc/emms.texinfo: small typo fix Thank you to Stefan Kangas <stefan@marxist.se>. commit ea9b8906c773b722d1c06c62bf5883b5a6de5342 Author: Yoni Rabkin <yoni@rabkins.net> Date: Tue Dec 20 15:09:56 2016 -0500 * lisp/emms.el: don't use obsolete variable `default-major-mode' commit cf6903c22b49b2e3efe338a9ccbd0df36b6d0cbf Author: Yoni Rabkin <yoni@rabkins.net> Date: Tue Nov 8 10:46:27 2016 -0500 * doc/developer-release.txt: add online manual update to list. commit d6b1628238e7b58620af4ad002dd3538a20ddea9 Author: Yoni Rabkin <yoni@rabkins.net> Date: Tue Nov 8 09:53:56 2016 -0500 * doc/developer-release.txt: add example commit 081edb0b426625efce8fd929d1ac4f9206e11010 Author: Yoni Rabkin <yoni@rabkins.net> Date: Tue Nov 8 09:44:13 2016 -0500 Update version for release. commit 6736d2e86d2909ef44759b1162e006bd5cc07547 Author: Yoni Rabkin <yoni@rabkins.net> Date: Mon Nov 7 18:15:04 2016 -0500 * lisp/emms-stream-info.el: Remove preference and document. Removes the built-in preference for mplayer, but also clearly documents how one would go about choosing either mplayer or vlc to query the streams. commit 591dbffe1449b5ba80885f2ce37ada4351d6417d Author: Yoni Rabkin <yoni@rabkins.net> Date: Tue Oct 25 10:50:33 2016 -0400 * NEWS: Update NEWS with previous work. commit 8484319bc2b6a7d7d281ad06d969cb592b804922 Author: Yoni Rabkin <yoni@rabkins.net> Date: Tue Oct 25 10:49:48 2016 -0400 Correct email address for maintainer. commit cbbe0980565bc6e9b83d04e11d11f4c7aed9ff4f Author: Yoni Rabkin <yoni@rabkins.net> Date: Tue Oct 25 10:25:55 2016 -0400 * Makefile: install emms-print-metadata commit 4148457ab5d314c05d3b7a1716e26a23f1c9c237 Author: Yoni Rabkin <yoni@rabkins.net> Date: Tue Oct 25 09:33:41 2016 -0400 * lisp/emms-stream-info.el: rename emms-stream-info-backend. commit 02c5183a484b12d529b0901a81604eb658bec8d3 Author: Yoni Rabkin <yrk@gnu.org> Date: Mon Aug 1 16:52:16 2016 -0400 * AUTHORS: add Daniel Dehennin <daniel.dehennin@baby-gnu.org> commit ad03c9cf42733e9c8ba5be54d2fac452c12ad09b Author: Yoni Rabkin <yrk@gnu.org> Date: Mon Aug 1 16:49:50 2016 -0400 * lisp/emms-tag-editor.el: fix "query-replace-read-args" Author: Daniel Dehennin <daniel.dehennin@baby-gnu.org> emms-tag-editor: fix “query-replace-read-args” use Since emacs commit 3ee4cd6482abbabb06630a6c725277d42061eee7[1] the retult value of “query-replace-read-args” changed which broke “emms-tag-editor-replace-in-tag”. * lisp/emms-tag-editor.el: Remove last two elements from query-replace-read-args results. Footnotes: [1] http://git.savannah.gnu.org/cgit/emacs.git/commit/?id=3ee4cd6482abbabb06630a6c725277d42061eee7 commit e63f143cce434aa17076ed6f437ed5bfd5db6d9d Author: Yoni Rabkin <yrk@gnu.org> Date: Mon Aug 1 11:43:48 2016 -0400 * lisp/emms-tag-editor.el: Make cons cell usable. Make cons cell usable when replacing a tag. Patch by Daniel Dehennin <daniel.dehennin@baby-gnu.org>. commit 92b982757880ffbe37ef8b2e7d6166c5440d94f0 Author: Yoni Rabkin <yrk@gnu.org> Date: Mon Aug 1 11:32:01 2016 -0400 * lisp/emms-tag-editor.el: Avoids FLAC tags dup. Avoids FLAC tags duplication with old values. Patch by Daniel Dehennin <daniel.dehennin@baby-gnu.org>. commit bec63d3ea62dafc4158c35abdf7e9180419a3f78 Author: Yoni Rabkin <yrk@gnu.org> Date: Sat Jul 9 12:33:04 2016 -0400 * Makefile: add .info suffix. Bug submitted by Alex Vong <alexvong1995@gmail.com>. commit 56373a1752582edbd0cb9881cf843d9f87cfcf56 Author: Yoni Rabkin <yrk@gnu.org> Date: Fri Jun 24 16:53:53 2016 -0400 * lisp/emms-streams.el: Remove defunct streams. Remove streams which are defunct for one reason or another. Patch thanks to Alejandro Erickson <alejandro.erickson@gmail.com>. commit bb8bb83cd83b02ba57e3283475d7fd2689ea5c33 Author: Yoni Rabkin <yrk@gnu.org> Date: Tue May 31 12:30:18 2016 -0400 * doc/developer-release.txt: add note commit c1e1a843c3389fc585908de367ff00fdd6470965 Author: Yoni Rabkin <yrk@gnu.org> Date: Tue May 31 12:23:43 2016 -0400 Prepare 4.1 release. commit ac15f46e19d259e5d49acdac877d0793be1c1ebe Author: Yoni Rabkin <yrk@gnu.org> Date: Mon Apr 11 15:42:05 2016 -0400 * lisp/tq.el: no need for tq.el apparently commit 0178d1c665f39838ca6fa7e53437cca15fa3a1de Author: Yoni Rabkin <yrk@gnu.org> Date: Fri Mar 4 12:20:00 2016 -0500 Add emms-show-all to NEWS and manual. commit 7b41cead0877e182caff609d59cf37c817ee8136 Author: Yoni Rabkin <yrk@gnu.org> Date: Tue Mar 1 12:44:00 2016 -0500 * lisp/emms-setup.el: add emms-show-all commit 7dc45e62de613e70556e6ffaf61cfb1a6706c788 Author: Yoni Rabkin <yrk@gnu.org> Date: Tue Mar 1 12:43:50 2016 -0500 * lisp/emms-show-all.el: fix compiler warning commit 59bb98c5c63b305259e677103badb001eec98896 Author: Yoni Rabkin <yrk@gnu.org> Date: Tue Mar 1 12:36:04 2016 -0500 * lisp/emms-show-all.el: first implementation commit 8ba0a5eb1991544ef91ea90772b614f9ab7d953c Author: Yoni Rabkin <yrk@gnu.org> Date: Sun Feb 28 22:03:16 2016 -0500 * lisp/emms-show-all.el: new file commit 6f630442faac593e19d04c21009674b310a98ed5 Author: Yoni Rabkin <yrk@gnu.org> Date: Sun Feb 28 09:49:26 2016 -0500 * doc/emms.texinfo: bump copyright year commit 141ab95c2a0a2554b205f6eec991fa36d7d0531f Author: Rasmus <rasmus@gmx.us> Date: Sun Feb 7 13:08:33 2016 +0100 Fix bug in emms-browser.el * lisp/emms-browser.el: setq requires an even number of arguments now. commit 489df29303fc89d4f80bffae91ad53f937ccd59a Author: Yoni Rabkin <yrk@gnu.org> Date: Fri Dec 11 14:55:11 2015 -0500 * NEWS: Update. commit 7efa5eae3ffba30335c466c1cfbbb62eab50786c Author: Yoni Rabkin <yrk@gnu.org> Date: Fri Dec 11 14:53:19 2015 -0500 * doc/emms.texinfo: Document the emms-setup.el change. commit 72d74b1b9af412f8ed4a8be69c3798dd904f6db3 Author: Yoni Rabkin <yrk@gnu.org> Date: Fri Dec 11 14:21:20 2015 -0500 * lisp/emms-setup.el: Depreciate emms-devel and emms-standard. The functions `emms-devel' and `emms-standard' are now synonymous with `emms-all' which loads everything. commit 04de0b50a5a572c2065073bdebbb18e3e2717e50 Author: Yoni Rabkin <yrk@gnu.org> Date: Fri Dec 11 12:36:25 2015 -0500 * doc/emms.texinfo: Make it read better. commit d3ef182013df50b411d9927715444401b4c64504 Author: Yoni Rabkin <yrk@gnu.org> Date: Thu Dec 10 18:22:37 2015 -0500 * doc/emms.texinfo: Reorganize. Move the Quickstart Guide chapter to the very beginning and re-write it to be the tl;dr of the manual. commit 0cd9cd79678c3bb21d97764bf1d75fabd4dd75c5 Author: Yoni Rabkin <yrk@gnu.org> Date: Thu Dec 10 18:22:22 2015 -0500 * doc/emms.texinfo: Out of date. commit 3c9c1562f12c79151c04158a760f7090629c3c4e Author: Yoni Rabkin <yrk@gnu.org> Date: Thu Dec 10 18:21:58 2015 -0500 * doc/emms.texinfo: Bump copyright year. commit 420070f079258b3800c466f2b80d9c8ce6984195 Author: Rasmus <rasmus@gmx.us> Date: Mon Aug 10 17:23:52 2015 +0200 emms-browser-goto-random only goes to lowest level emms-browser-goto-random only considers item of lowest level. For instance, in level 2 emms-browser-goto-random will only stop once an albums has been found and so forth. commit f1c504eae7a46d24e679c992c093b8bcd63ab32b Author: Rasmus <rasmus@gmx.us> Date: Mon Aug 10 16:44:10 2015 +0200 Sort using locale language in the browser - Use string-collate-lessp if available for alphabetic sorting. - Use emms-browser-alpha-sort-function to sort in the browser. commit 55ff581b1e7d8b0b290834e87221baadd95db1ff Author: Rasmus <rasmus@gmx.us> Date: Tue May 19 16:36:41 2015 +0200 emms-url: add emms-url-quote-underscore The function is used in emms-lyrics, but was not commited previously. commit 167d1efabfcffb5e1e2aacc8dcb7225d33eb4b32 Author: Yoni Rabkin <yrk@gnu.org> Date: Mon Mar 30 11:28:26 2015 -0400 * NEWS: Add https support. commit e7b16fa8b114b80e4752df5db370bdee233a4093 Author: Yoni Rabkin <yrk@gnu.org> Date: Sun Mar 29 22:45:17 2015 -0400 * lisp/emms-setup.el: Bug fix: Add missing default player. commit 4088cda083823455512369a66a82769ff7eae9ed Author: Yoni Rabkin <yrk@gnu.org> Date: Sun Mar 29 22:44:14 2015 -0400 Add https as a recognizable connection option. Note that not all backends know how to play through an https connection. commit 1ca398268d28644bb955560612ed881d783078d0 Author: Yoni Rabkin <yrk@gnu.org> Date: Sun Mar 29 22:42:41 2015 -0400 Move librefm to https. Note that some player backends don't know how to handle https. commit 7df41c3237a6e855d0568bf9b67642cab61a8184 Author: Rasmus <rasmus@gmx.us> Date: Sun Mar 22 13:15:38 2015 +0100 emms-browser: fix bug in 9e48ab1a move emms-volume directly to emms-browser mode map. commit 6bc53c76eadaee1ba37d6301c28ac987d77c0124 Author: Rasmus <rasmus@gmx.us> Date: Sun Mar 15 17:31:30 2015 +0100 emms-lyrics: Use eww if present to display lyrics Lyrics are now fetched from lyricwiki.org. It is possible to change the url, but it assumes a certain order of the format string. commit 9e48ab1ab4cdeee69bfa8d327b54f85f6a54115f Author: Rasmus <rasmus@gmx.us> Date: Sun Mar 15 16:42:59 2015 +0100 emms-volume: Also support the emms-browser Also bind +/- to emms-volume commands in the browser. commit c31de7a307a996a601bcc8e458674cef41f58358 Author: Yoni Rabkin <yrk@gnu.org> Date: Mon Mar 16 21:29:45 2015 -0400 Added setting volume via PulseAudio. Possible to set volume via PulseAudio pactl via emms-volume-pulse.el. Patch by Rasmus Pank Roulund <emacs@pank.eu>. commit a2f4ee1aeaf433801b57163829b969b5a055949a Author: rasmus <rasmus@gmx.us> Date: Tue Mar 10 12:55:27 2015 +0100 Fix bug in introduced in 428d662 - emms.texinfo: used wrong variable. - emms-librefm-scrobbler.el: remove warning. commit 428d6628917a3a413a0da30be2192c8822cc5db1 Author: rasmus <rasmus@gmx.us> Date: Sun Mar 8 21:03:25 2015 +0100 emms-librefm-scrobbler.el: Add Commentary-section Add minimal instructions on how to enable scrobbling. commit d12e1dc2cfd8773c8c7bfb207e2fbcaad9d674a5 Author: Rasmus <rasmus@gmx.us> Date: Tue Jul 29 15:31:06 2014 +0200 emms-info libtag.el: Easier to add new extension * emms-print-metadata.c (main): Better error message. * emms-info-libtag.el (emms-info-libtag): New group. (emms-info-libtag-program-name): Change to defcustom. (emms-info-libtag-known-extensions): New variable. (emms-info-libtag): Use emms-info-libtag-known-extensions. Two changes: First, emms-info-libtag tells the user that it may work with other forms. Since emms-info-libtag-known-extensions is now a regexp variable so users can easily add new extensions, if needed. commit 3f3dc1058db5f7accbc06e80e9ad329aec2ef434 Author: Rasmus <rasmus@gmx.us> Date: Tue Jul 29 12:59:38 2014 +0200 emms-librefm-scrobbler.el: use authinfo The recommended way to store libre.fm login details are now via authinfo. See emms-librefm-scrobbler--username, emms-librefm-scrobbler--password and the manual. commit dbcdc8513919dde524dcf2fa434a4b8e4770e57f Author: rasmus <x200s@pank.eu> Date: Sun Mar 8 19:52:15 2015 +0100 Add Rasmus to AUTHORS. commit 09f5512e348213af7095f150bb5f7546971d482f Author: rasmus <x200s@pank.eu> Date: Sun Mar 8 19:52:02 2015 +0100 Handle covers with different file extensions Covers are can now have different file extensions. See emms-browser-covers-file-extensions. The first file from emms-browser--covers-filename, which is build when needed, is used. commit e248dcd4b9bf1763fc84c719c745f7d23f06b13c Author: Yoni Rabkin <yrk@gnu.org> Date: Tue Dec 2 15:02:58 2014 -0500 * lisp/emms-player-simple.el: Remove old documentation. commit 857229ca8fa7f058e956cf9dcfbae19d23f2e50b Author: Yoni Rabkin <yrk@gnu.org> Date: Tue Dec 2 15:01:39 2014 -0500 Add and use variable `emms-player-base-format-list'. This variable holds the set of common formats that most modern players support. A new player definition should use this base list and add formats specific to the new player in the player definition file. commit 65550e4d2afbd2f9d068539e0867f91ec16b068b Author: Yoni Rabkin <yrk@gnu.org> Date: Tue Nov 4 15:38:50 2014 -0500 Add aif files to the recognized file types. commit 9b227a807b84151ae4cbb60b47a27046ce1d84fe Author: Yoni Rabkin <yrk@gnu.org> Date: Sat Oct 25 20:18:32 2014 -0400 * THANKGNU: Be a bit more thankful. commit d67c1a10a62e81088d5a49cbf13f9247804cfe6e Author: Yoni Rabkin <yrk@gnu.org> Date: Sat Oct 25 20:17:20 2014 -0400 Change the way lines are killed in emms-playlist-mode. This change was requested by Rasmus and Michael Olson. commit 6b5fa99bbecaace60d0879f54b5e6fa74bbc84a1 Author: Yoni Rabkin <yonirabkin@member.fsf.org> Date: Sun Oct 19 22:24:42 2014 -0400 Use commit logs to move people between AUTHORS and THANKGNUs. commit cf547c5df1bf18e243b822626bf3af1b9d60d6ac Author: Yoni Rabkin <yonirabkin@member.fsf.org> Date: Sun Oct 19 22:05:57 2014 -0400 * AUTHORS: Add Nick Alcock. commit 50846d2271f8058debe8e8b870dd1fdb9a362085 Author: Yoni Rabkin <yonirabkin@member.fsf.org> Date: Sat Oct 18 22:02:52 2014 -0400 * THANKGNU: Add THANKGNUs based on commit records. commit 9064f95f5b4cc1f66d4ad6173b25532946e70524 Author: Yoni Rabkin <yonirabkin@member.fsf.org> Date: Sat Oct 18 22:02:35 2014 -0400 * AUTHORS: Add to AUTHORS based on commit records. commit 5a3c93d3c8132f8235c8a80d1779c490534910e7 Author: Yoni Rabkin <yonirabkin@member.fsf.org> Date: Wed Oct 15 23:09:09 2014 -0400 * doc/emms.texinfo: Document emms-print-metadata. commit 36274e2f2c25d27d7679a78a98e813d5336687ff Author: Yoni Rabkin <yonirabkin@member.fsf.org> Date: Tue Oct 14 12:26:32 2014 -0400 Move Jesse Weinstein's contribution to the new THANKGNU file. commit e03288e8d660e18cd55f5707447843212811c78f Author: Yoni Rabkin <yonirabkin@member.fsf.org> Date: Mon Oct 13 20:11:10 2014 -0400 * src/emms-print-metadata.c: Fix crash. Short (4 lines) contrib from Arnaud Fontaine <arnau@debian.org>. See: https://bugs.debian.org/cgi-bin/bugreport.cgi?bug=715864 also: https://vcs-git-viewer.duckcorp.org/?p=people/arnau/emms.git;a=commit;h=27825228ba9d62902b75c45b1ffee3893b22cea8 commit 22ca956b821e44802446d1ee8e412d6790ce17f4 Author: Yoni Rabkin <yonirabkin@member.fsf.org> Date: Wed Aug 20 15:51:38 2014 -0400 Add thing-at-point to interactive input. Patch by Daimrod <daimrod@gmail.com>. Change too small for copyright papers. commit 96c9802e97742be2e44482f2ea16123436b35fd6 Author: Yoni Rabkin <yonirabkin@member.fsf.org> Date: Wed Aug 20 15:51:15 2014 -0400 * lisp/emms-source-file.el: Add customization parameters. Patch by Daimrod <daimrod@gmail.com>. Change too small for copyright papers. commit da3870519dffd9a04e0683caff974cdedd6e356d Author: Yoni Rabkin <yonirabkin@member.fsf.org> Date: Wed Aug 20 15:42:47 2014 -0400 Add FLV and WEBM formats. Patch by Daimrod <daimrod@gmail.com>. Change too small for copyright. commit 43a32aefb6a175bdd41ea2342d0acdae5591d988 Author: Yoni Rabkin <yonirabkin@member.fsf.org> Date: Sun Aug 3 01:09:37 2014 -0400 * doc/emms.texinfo: Add documentation note. Thanks to Alexis <flexibeast@gmail.com>. commit 7d555717a18520cdb8d0f765296a01742377d204 Author: Yoni Rabkin <yonirabkin@member.fsf.org> Date: Mon Jul 28 18:10:14 2014 -0400 Correct documentation. Changes by Alexis <flexibeast@gmail.com>. commit 20d90b02ad06e1e604c985f1fc328d72feafb888 Author: Yoni Rabkin <yonirabkin@member.fsf.org> Date: Mon Jul 28 18:09:51 2014 -0400 * Makefile: Update ftp.gnu.org push script to 1.2. commit 8c3d80db566c96255b31b4ca8826c858a1a1cfb7 Author: Yoni Rabkin <yonirabkin@member.fsf.org> Date: Mon Jun 30 15:05:41 2014 -0400 Bump makefile release version. commit b6cac2188d736452124aaabc86edf8baf97abe21 Author: Yoni Rabkin <yonirabkin@member.fsf.org> Date: Mon Jun 30 15:03:48 2014 -0400 * README: Remove unnecessary duplication. Left a pointer to the fine manual. commit 82b7a7a5d9d1a898b63b2e3660283e284480e89c Author: Yoni Rabkin <yonirabkin@member.fsf.org> Date: Mon Jun 30 14:58:34 2014 -0400 * lisp/emms.el: Bump version. commit 86bc1218d4d316cffd07a3adc592585a1b4f79d2 Author: Yoni Rabkin <yonirabkin@member.fsf.org> Date: Mon Jun 30 14:47:32 2014 -0400 * AUTHORS: Sort author entries alphabetically. M-x sort-lines commit ae7c7cfef9528c7ce8b24d3be43cd41313e72521 Author: Yoni Rabkin <yonirabkin@member.fsf.org> Date: Mon Jun 30 14:35:41 2014 -0400 * AUTHORS: Add Jose Antonio Ortega Ruiz. commit f27679b5e71c9abed75e662e2e0923fcb9ee3a66 Author: Yoni Rabkin <yonirabkin@member.fsf.org> Date: Mon Jun 30 14:34:41 2014 -0400 * lisp/emms-player-mpd.el: Fix MPD listinfoall. Patch by Jose Antonio Ortega Ruiz <jao@gnu.org>. commit 6b58bd4167e232cdaaf032c0959e4b1c43b21e9c Author: Yoni Rabkin <yonirabkin@member.fsf.org> Date: Sun Jun 1 11:51:44 2014 -0400 * NEWS: Update. commit 90e8fcee1a5792446074f4b2a381877dbee6c7c6 Author: Yoni Rabkin <yonirabkin@member.fsf.org> Date: Fri May 30 13:30:56 2014 -0400 * Makefile: Only use ginstall-info if it exists. commit e62987b494c8ca8a63adec30e92aab3443ba0951 Author: Yoni Rabkin <yonirabkin@member.fsf.org> Date: Thu May 29 14:17:24 2014 -0400 * lisp/emms.el: Add new display function. Idea from by Ian D <dunni@gnu.org>. commit 603fbd85e7ac35c2b8edbcd4c15f5d74c767aaaf Author: Yoni Rabkin <yonirabkin@member.fsf.org> Date: Thu May 29 14:13:54 2014 -0400 * AUTHORS: Add note. commit 3ef7a0c0cc0711defb876b00d3eac36baf1ffded Author: Yoni Rabkin <yonirabkin@member.fsf.org> Date: Thu May 29 13:03:37 2014 -0400 * Makefile: Update to GNU install-info. commit a6baeec15ee331c90907414f0e21592460765ed6 Author: Yoni Rabkin <yonirabkin@member.fsf.org> Date: Tue Apr 22 14:17:02 2014 -0400 * lisp/emms-tag-editor.el: Use newer paradigm. commit 5f026f84a9024305382eff2ee933088ad29088c3 Author: Yoni Rabkin <yonirabkin@member.fsf.org> Date: Tue Apr 22 14:09:44 2014 -0400 * lisp/emms-streams.el: Use newer paradigm. commit 31984d8868e09264271fb2dfb59bd207cb6816b2 Author: Yoni Rabkin <yonirabkin@member.fsf.org> Date: Tue Apr 22 14:08:20 2014 -0400 * lisp/emms-source-file.el: Add required code. commit 581c8d7a92cd10911012fde6a2f71779d36e4111 Author: Yoni Rabkin <yonirabkin@member.fsf.org> Date: Tue Apr 22 13:45:07 2014 -0400 * lisp/emms-player-mpd.el: Require code which provides emms-url-... functions. commit f5accc0425e173fe49a705fe56db90ca0cd6ab33 Author: Yoni Rabkin <yonirabkin@member.fsf.org> Date: Tue Apr 22 13:41:53 2014 -0400 * lisp/emms-player-mpd.el: Require the code which provides emms-cache-db. commit 72d47f6eed655abd675b59abfd4c0c8af97680d9 Author: Yoni Rabkin <yonirabkin@member.fsf.org> Date: Tue Apr 22 13:22:55 2014 -0400 * lisp/emms.el: Replace obsolete function. This has the pleasant side effect of quietening the compiler. commit 33947ba1bfbae48196d51e10c00c72fa24380e64 Author: Yoni Rabkin <yonirabkin@member.fsf.org> Date: Tue Apr 22 13:16:25 2014 -0400 * lisp/emms-compat.el: Hush the compiler about hl-line-highlight. commit 009f2a9ee705c0acc140872f9af67b331770e6d1 Author: Yoni Rabkin <yonirabkin@member.fsf.org> Date: Tue Apr 22 13:11:03 2014 -0400 * NEWS: Add a note. commit 105ba97606bb5d68a3032d9c8af406ac9e9ebac1 Author: Yoni Rabkin <yonirabkin@member.fsf.org> Date: Fri Apr 18 22:00:06 2014 -0400 * NEWS: Update news. commit cb1c92b87139272718d85d0874e818846214b645 Author: Yoni Rabkin <yonirabkin@member.fsf.org> Date: Thu Apr 17 17:27:35 2014 -0400 * FAQ: Remove this file. This is an ancient file of doubtful use. commit c2159209b01e45095184d31404cb10d10b4bbbc9 Author: Yoni Rabkin <yonirabkin@member.fsf.org> Date: Thu Apr 17 17:21:59 2014 -0400 * doc/emms.texinfo: Space out nodes. This makes editing a bit easier. commit 0ea0b72c4b4026774f6c1dcbd8ac00fdae559358 Author: Yoni Rabkin <yonirabkin@member.fsf.org> Date: Thu Apr 17 17:21:23 2014 -0400 * doc/Makefile: Add clean target. commit e9abbf6fab3eeb084d366c394868bba2f8639b49 Author: Yoni Rabkin <yonirabkin@member.fsf.org> Date: Mon Apr 7 13:28:23 2014 -0400 * doc/emms.texinfo: Document GNU FM support. commit 6c638958dd4a3b4c90b78359a6ac467c174fc4ed Author: Yoni Rabkin <yonirabkin@member.fsf.org> Date: Sun Apr 6 23:52:11 2014 -0400 Solve dependencies and compiler issues. commit 6e650a9ad6d0091ffb448487563dc7e799a99af2 Author: Yoni Rabkin <yonirabkin@member.fsf.org> Date: Sun Apr 6 23:35:33 2014 -0400 * lisp/emms-source-file.el: Remove lastfm url autoload. commit fe5ba15cdac9ac124b5286f3c67b40b85b61eb90 Author: Yoni Rabkin <yonirabkin@member.fsf.org> Date: Sun Apr 6 23:30:20 2014 -0400 Remove lastfm code. commit de1ace05b3c76c7195c0e898d61b6346f769ff94 Author: Yoni Rabkin <yonirabkin@member.fsf.org> Date: Sun Apr 6 23:27:41 2014 -0400 * lisp/emms-setup.el: Add to setup. commit ac0ae7719268fc430dce8b395d131db055cd6435 Author: Yoni Rabkin <yonirabkin@member.fsf.org> Date: Sun Apr 6 23:26:04 2014 -0400 Add continuous streaming. commit d7572520abe1b95c25f9f2f6c1ab50ca927f3541 Author: Yoni Rabkin <yonirabkin@member.fsf.org> Date: Thu Apr 3 20:27:42 2014 -0400 * lisp/emms-librefm-stream.el: Convert playlist to Emms tracks. commit 9797d3ec430628a3ae3c56df40656af38da3af58 Author: Yoni Rabkin <yonirabkin@member.fsf.org> Date: Thu Apr 3 14:45:32 2014 -0400 * lisp/emms-librefm-stream.el: Implement getting a playlist. commit 56c71749e76b3836a1106febc805bec7764cff79 Author: Yoni Rabkin <yonirabkin@member.fsf.org> Date: Wed Apr 2 14:47:43 2014 -0400 * lisp/emms-librefm-stream.el: Implement radio handshake call. commit ed6f5924c620ddf529c77602bfafbd68f28fc04a Author: Yoni Rabkin <yonirabkin@member.fsf.org> Date: Tue Apr 1 14:57:09 2014 -0400 * lisp/emms-lyrics.el: Fix bug; the correct tag is info-title. commit 431595d1f1d8e789a3fdedc95223c9d45afbf114 Author: Yoni Rabkin <yonirabkin@member.fsf.org> Date: Tue Apr 1 14:49:18 2014 -0400 * lisp/emms-librefm-stream.el: Add file. commit eafe8228d259a15d21f517bb2bdf54b09c0b49dd Author: Yoni Rabkin <yonirabkin@member.fsf.org> Date: Sat Mar 29 00:29:33 2014 -0400 * lisp/emms-setup.el: Add to setup. commit 266048a31cfcce5599e257656cf5d964bef8d59c Author: Yoni Rabkin <yonirabkin@member.fsf.org> Date: Sat Mar 29 00:29:20 2014 -0400 * lisp/emms-librefm-scrobbler.el: Correctly handle the session id. commit 0814939bd077c8020e17baaaffff866acf0fc62b Author: Yoni Rabkin <yonirabkin@member.fsf.org> Date: Fri Mar 28 23:58:54 2014 -0400 * lisp/emms-librefm-scrobbler.el: Display messages by default. commit 6fc1e5cc7a8201f9daeefd5675558cc968e6b8fc Author: Yoni Rabkin <yonirabkin@member.fsf.org> Date: Fri Mar 28 23:36:53 2014 -0400 * lisp/emms-librefm-scrobbler.el: Complete working libre.fm scrobbler. commit a08da82ecd0949c1abebd3bfc149cb08ed41a389 Author: Yoni Rabkin <yonirabkin@member.fsf.org> Date: Mon Mar 10 17:31:24 2014 -0400 Rename commit c578f5783972b7090014895af4e08a36d20d7c2b Author: Yoni Rabkin <yonirabkin@member.fsf.org> Date: Mon Mar 10 10:48:15 2014 -0400 * lisp/emms-librefm-client.el: Implement handshake commit fc4275f6c6d31a73875f649f884bf1bcf04e3448 Author: Yoni Rabkin <yonirabkin@member.fsf.org> Date: Sun Mar 9 23:42:10 2014 -0400 * lisp/emms-librefm-client.el: initial file commit commit 2b9b83025850ce28ba9079811c8b89b1d6e3b39f Author: Yoni Rabkin <yonirabkin@member.fsf.org> Date: Fri Mar 7 09:03:36 2014 -0500 * AUTHORS: Update email. commit a488db8a8527438bd42a9ecb0bc2d925cf1412a5 Author: Yoni Rabkin <yonirabkin@member.fsf.org> Date: Sat Feb 22 23:27:17 2014 -0500 * lisp/emms-tag-editor.el: Silence the compiler by explicitly passing `filename'. commit bd85ebf4d2b92226e77709bfbcb635b58c94a228 Author: Johnathan Rabkin <yonirabkin@member.fsf.org> Date: Sat Feb 22 22:45:31 2014 -0500 Fix compilation warnings. commit 2421caf63006e310f85a97143ba83f4f1b0d8391 Author: Johnathan Rabkin <yonirabkin@member.fsf.org> Date: Sat Feb 22 22:30:01 2014 -0500 * lisp/emms-setup.el: Remove Last.fm extension from setup. This code currently doesn't work, so we don't need it loaded in the setup. commit 55e55efa6cac831c4266dc5c72e1e44da6db7336 Author: Johnathan Rabkin <yonirabkin@member.fsf.org> Date: Sat Feb 22 22:17:10 2014 -0500 * doc/emms.texinfo: Remove reference to Last.fm support. Last.fm support has failed to track the API and licensing changes over at Last.fm. While I wouldn't remove the code just yet, we should remove it from the manual so that people don't get the impression that it is actually working. commit c10e28076ccec49828bd544fb2dda67c55bcdbc9 Author: Johnathan Rabkin <yonirabkin@member.fsf.org> Date: Wed Oct 16 12:32:47 2013 -0400 * lisp/emms-info-libtag.el: Added mp4, m4a to the extensions handled by emms-info-libtag Patch thanks to Mandar Mitra. commit 2fba6182e3cabe5fc4002473b16ee47e62e95683 Author: Johnathan Rabkin <yonirabkin@member.fsf.org> Date: Wed Aug 21 10:48:29 2013 -0400 * lisp/emms-streams.el: Fix compilation error; update obsolete variable. commit 39e2c28f74d01e151709bf7e89989b740a5d75fb Author: Johnathan Rabkin <yonirabkin@member.fsf.org> Date: Mon Aug 19 00:15:54 2013 -0400 * doc/gpl.texi: Fix compilation under texinfo 5.1 The "@enumerate 0" for the "TERMS AND CONDITIONS" section should finish before the "END OF TERMS AND CONDITIONS" heading. The "@end enumerate" line is currently in the wrong place, so move it. Fix thanks to Katherine Whitlock. commit 8d3a0e035d09a433cdac8a15a5a3d41bdc475bd1 Author: Johnathan Rabkin <yonirabkin@member.fsf.org> Date: Fri Aug 16 13:30:30 2013 -0400 * doc/emms.texinfo: Close @defun statement. commit bc052418b84f343478e80f9dde44a419de9fd6ee Author: Johnathan Rabkin <yonirabkin@member.fsf.org> Date: Fri Aug 16 13:27:37 2013 -0400 * lisp/emms-score.el: Stop `emms-score-load-hash' from reading empty score file. Reads the score file into a string, then only proceeds if the string is not empty. I ran it myself, and appears to be working correctly. Thanks to Ian D. commit 5d8b53a421fd7bf486316a81ee4e7ab0658c17a9 Author: William Xu <william.xwl@gmail.com> Date: Tue Aug 13 19:55:05 2013 +0800 (emms-lyrics-set-timer): Don't repeat lyrics already displayed when resumed. When resuming from a paused session, played lyrics timers will have a negative time, but timer-duration is so nice to convert it as positive, thus messing lyrics display. Check the `time' to fix. Thanks to Ian D. commit c763540c3473e06405825d6f1679f97b99567de9 Author: Daimrod <daimrod@gmail.com> Date: Thu May 30 14:09:26 2013 +0200 Play tracks randomly [[PGP Signed Part:Undecided]] Lucas Bonnet <lucas@rincevent.net> writes: > Yoni Rabkin <yoni@rabkins.net> writes: > >> Daimrod <daimrod@gmail.com> writes: >> >>> Yoni Rabkin <yoni@rabkins.net> writes: >>> >>>> Daimrod <daimrod@gmail.com> writes: >>>> >>>>> Hello, >>>>> >>>>> I've attached a small patch which adds `emms-toggle-random-playlist'. It >>>>> sets `emms-player-next-function' to either `emms-next-noerror' or >>>>> `emms-random'. >>>> >>>> How is this different from running M-x emms-shuffle on the playlist? >>> >>> I agree they're close, but this one doesn't shuffle the playlist and it >>> persists when the playlist is changed. >> >> I certainly have no problem with it; I was just making sure you were >> aware of emms-shuffle. >> >> If Lucas is fine with installing it (I don't think it needs assignment >> papers) I would ask that you please also send in a patch to the manual >> documenting this change. > > I'd say it's small enough to fly below the copyright papers radar :) > > Thanks for your patch! > > Regards, Oops, there is a small typo in the patch, here is the fix. Sorry for the inconvenience. [2. text/x-diff; 0001-lisp-emms.el-emms-toggle-random-playlist-Fix-typo-in.patch] From 33041798b58d68f76cd8006915bb153a94769e9b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Gr=C3=A9goire=20Jadi?= <gregoire.jadi@gmail.com> Date: Thu, 30 May 2013 14:07:58 +0200 Subject: [PATCH] lisp/emms.el (emms-toggle-random-playlist): Fix typo in code * lisp/emms.el (emms-toggle-random-playlist): Fix typo in code. commit a8563e6d3f80c26434e61752e2e43420bfcdd81b Author: Daimrod <daimrod@gmail.com> Date: Fri May 10 19:49:58 2013 +0200 Play tracks randomly [[PGP Signed Part:No public key for 137354772B651894 created at 2013-05-10T19:49:58+0200 using RSA]] Yoni Rabkin <yoni@rabkins.net> writes: > Daimrod <daimrod@gmail.com> writes: > >> Yoni Rabkin <yoni@rabkins.net> writes: >> >>> Daimrod <daimrod@gmail.com> writes: >>> >>>> Hello, >>>> >>>> I've attached a small patch which adds `emms-toggle-random-playlist'. It >>>> sets `emms-player-next-function' to either `emms-next-noerror' or >>>> `emms-random'. >>> >>> How is this different from running M-x emms-shuffle on the playlist? >> >> I agree they're close, but this one doesn't shuffle the playlist and it >> persists when the playlist is changed. > > I certainly have no problem with it; I was just making sure you were > aware of emms-shuffle. > > If Lucas is fine with installing it (I don't think it needs assignment > papers) I would ask that you please also send in a patch to the manual > documenting this change. I have already made a copyright assignment for Emacs and I have no problem to do it for EMMS if it is required. I've attached the patch with the documentation. [2. text/x-diff; 0001-New-command-to-play-the-tracks-randomly.patch] From b03cb56436a598a953fa49b456a88630f319b644 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Gr=C3=A9goire=20Jadi?= <gregoire.jadi@gmail.com> Date: Fri, 10 May 2013 19:44:59 +0200 Subject: [PATCH] New command to play the tracks randomly * lisp/emms.el (emms-random-playlist): An option to determine whether the tracks are played randomly or sequentially. (emms-toggle-random-playlist): Trigger the previous option and set `emms-play-next-function' accordingly. * doc/emms.texinfo(Core Functions): Document`emms-toggle-random-playlist'. commit 82e8bdd7a748921eb3ac4723d9c176391db9ccd5 Author: Lucas Bonnet <lbonnet@bearstech.com> Date: Sun Jan 27 17:08:59 2013 +0100 * src/emms-print-metadata.pl: New implementation to read most (if not all) tags using a single program, with the help of Audio::Scan (see http://search.cpan.org/~agrundma/Audio-Scan-0.93/lib/Audio/Scan.pm). commit d182e67e31420d7eb442151a1106faa8930f0b5d Author: Arnaud Fontaine <arnau@debian.org> Date: Thu May 24 12:29:36 2012 +0900 Makefile: add missing $(CPPFLAGS) to compiler. commit b82c4e3ec155b3749e9a59c52d168460b24c636c Author: Arnaud Fontaine <arnau@debian.org> Date: Thu May 24 10:37:04 2012 +0900 Rename too generic name generate-autoloads to emms-generate-autoloads. * lisp/emms-auto.in/emms-generate-autoloads: rename from generate-autoloads. * Makefile: call emms-generate-autoloads rather than generate-autoloads. commit 5b0d66139a740ebe42e45eadc908daed3e2f7736 Author: Arnaud Fontaine <arnau@debian.org> Date: Thu May 24 09:59:56 2012 +0900 Support both XEmacs and Emacs to highlight playing lyrics. * lisp/emms-compat.el: support highlighting for both XEmacs (highlight) and Emacs (hl-line). * lisp/emms-lyrics.el: use compatibility functions defined in emms-compat.el. commit 8b313708a9bce6611ba0b5e74e6c08b1dead3842 Author: Arnaud Fontaine <arnau@debian.org> Date: Sat Nov 5 15:49:57 2011 +0900 Remove emms-playlist-sort-by-score from documentation. Followup of f57b1526ff9219b70f6de29b5808257750b2ae0c. commit e5a23039a7b6c77b61edb64f6b111beff3236c19 Author: Arnaud Fontaine <arnau@debian.org> Date: Sat Nov 5 15:28:21 2011 +0900 * lisp/emms-history.el: Don't set `kill-emacs-hook' on noninteractive sessions. From Emacs 24.1, `kill-emacs-hook' is ran even in batch mode (commit 1e5ffe30b3f7682ee8467e7694b5f63371e31cf9). As a consequence, upon Debian package installation, byte compilation fails at the end as /root/.emacs.d/emms/ does not exist and should not be created neither. commit 78c9cc464f8e9be777afc1ba82ee73b86abf3d06 Author: Johnathan Rabkin <yonirabkin@member.fsf.org> Date: Sun Oct 14 20:08:16 2012 -0400 * lisp/emms-player-mpd.el (emms-player-mpd-get-supported-regexp): extend the supported formats scanning to the new (0.17) output of `mpd --version', keeping the previous scanners for earlier versions. We include not only file extensions, but also supported network protocols, which are also reported by mpd. Patch by Jose Antonio Ortega Ruiz <jao@gnu.org> commit d73e52d4d6abb324e93584d01f53d360f57834a9 Author: Johnathan Rabkin <yonirabkin@member.fsf.org> Date: Thu Sep 20 07:32:31 2012 -0400 * lisp/emms-browser.el: Fix bug in use of compare-strings. The standard use of compare-strings in this manner is (eq t (compare-st...)). commit d5666db21b9e2832eedf4d63a35d29f7fea7135b Author: Johnathan Rabkin <yonirabkin@member.fsf.org> Date: Tue Sep 18 12:28:50 2012 -0400 Add support for disc-number sorting of FLAC files. Patch from Christophe Rhodes <csr21@cantab.net>. commit 7a5eb54fa0f4a0d91213ec91263bfacc0469bc55 Author: Johnathan Rabkin <yrk@rabkins.net> Date: Tue Sep 18 12:01:25 2012 -0400 * lisp/emms-lastfm-client.el: Remove unnecessary requirements. This also resolves a compile error. commit 5aec397dc8c706b7aab6f1a5a455388f85303ce1 Author: Johnathan Rabkin <yrk@rabkins.net> Date: Tue Sep 18 11:57:27 2012 -0400 * lisp/emms-lastfm-scrobbler.el: Add requirement. This will reduce the number of warnings as to free variable references during compilation. commit 434c9d782207a053a5b117069b659df2f1c989ba Author: Johnathan Rabkin <yrk@rabkins.net> Date: Tue Sep 18 11:56:33 2012 -0400 * lisp/emms-lastfm-scrobbler.el: Remove debugging code. commit 298e022d7fba7a991fcc9cf25306a7b8eb8a612e Author: Lucas Bonnet <lucas@rincevent.net> Date: Mon Apr 25 18:51:28 2011 +0200 * lisp/emms-browser.el (emms-browser-track-duration): New function to allow custom browser track-formats to display track duration. commit 2374a3c8868f109543453ef7a269ad2d580b7cdc Author: Lucas Bonnet <lucas@rincevent.net> Date: Mon Apr 25 18:29:03 2011 +0200 * lisp/emms-browser.el: fix typo in comment commit 716975560a3385c4955ef1481f4994567dc66830 Author: Arnaud Fontaine <arnau@debian.org> Date: Tue Apr 19 06:14:10 2011 +0200 Create cache directory if it does not already exist. Following the quickstart guide, then adding a directory tree after creating a playlist, an error message is displayed upon leaving Emacs as the cache directory does not exist. Signed-off-by: Lucas Bonnet <lucas@rincevent.net> commit e87bcd69dfcdc63888933cc04bab2081e10494b7 Author: Arnaud Fontaine <arnau@debian.org> Date: Tue Apr 19 06:14:09 2011 +0200 When generating ChangeLog file, do not show the merges. Signed-off-by: Lucas Bonnet <lucas@rincevent.net> commit f99a5002cb1aa8791a88c06dec21ecb3b4a15eea Author: Yoni Rabkin <yoni@rabkins.net> Date: Tue Feb 1 20:45:49 2011 -0500 * lisp/emms-lastfm-client.el: Add support for PNG files. commit f505c6940725103c122adf9eded90d381f971a26 Author: Yoni Rabkin <yoni@rabkins.net> Date: Thu Jan 27 20:20:07 2011 -0500 * doc/emms.texinfo: Document emms-lastfm-client-info. commit 10f15c1aad77a92fa6ac180454f4b53f73f22c55 Author: Yoni Rabkin <yoni@rabkins.net> Date: Thu Jan 27 20:11:20 2011 -0500 * lisp/emms-lastfm-client.el: Implement artist.getInfo. commit b416748e47b3573ae8f0d5d558cb4d8d70a4ebfd Author: Yoni Rabkin <yoni@rabkins.net> Date: Thu Jan 27 20:08:08 2011 -0500 Update copyright years. commit 4bb75d5f7304d1a986ff0508bce8700100908849 Author: Dirk-Jan C. Binnema <djcb.bulk@gmail.com> Date: Sun Jan 2 11:38:29 2011 +0200 * emms-source-playlist-parse-pls: add support for parsing file://-uris in pls-files commit 11831694fed9bb73fce80fb3e288cc490c2a8f65 Author: Yoni Rabkin <yoni@rabkins.net> Date: Sun Dec 5 22:01:37 2010 -0500 * doc/emms.texinfo: Document new station. commit 6d7dfa890c90e0aa11c19d4751972aedb04f14b7 Author: Yoni Rabkin <yoni@rabkins.net> Date: Sun Dec 5 22:00:07 2010 -0500 * lisp/emms-lastfm-client.el: Add station. commit 1126baf19b5c94c5abdd76c81b5ea3bc8e0e123f Author: Yoni Rabkin <yoni@rabkins.net> Date: Fri Oct 29 18:09:33 2010 -0400 * doc/emms.texinfo: Record Last.fm station changes. commit 65403dac8dc420db93d0374851ce5856fc12725f Author: Yoni Rabkin <yoni@rabkins.net> Date: Fri Oct 29 18:02:59 2010 -0400 * lisp/emms-lastfm-client.el: Add Last.fm station. commit f33c4aae2185e6f7d12721c4aa96f80403b51ba0 Author: Yoni Rabkin <yoni@rabkins.net> Date: Thu Sep 16 21:44:47 2010 -0400 * AUTHORS: Add author. commit de3c04a2ee4916f171ee32a91fa302a0eaed427d Author: Yoni Rabkin <yoni@rabkins.net> Date: Thu Sep 16 21:43:49 2010 -0400 Add scrobbling of local tracks to Last.fm support. From: Bram van der Kroef <bram@fortfrances.com> commit e6aba649520ec44425060863e1c35ed01c53fd4b Author: Lucas Bonnet <lucas@rincevent.net> Date: Wed Aug 11 14:14:18 2010 +0200 Makefile: the clean target now removes emms-print-metadata binary in src/ commit d6ab4340d9c20f7aa501c66c557023365ae60f09 Author: Lucas Bonnet <lucas@rincevent.net> Date: Wed Aug 11 00:10:14 2010 +0200 Makefile: now using Git, so get rid of darcs in ChangeLog Makefile target. Patch by Arnaud Fontaine <arnaud@debian.org> commit c10ea241e3da219126a6d6d3b9f88c359270e70d Author: Lucas Bonnet <lucas@rincevent.net> Date: Wed Aug 11 00:04:23 2010 +0200 Makefile: add CFLAGS and $LDFLAGS, based on a patch by Christian Faulhammer <fauli@gentoo.org> commit 8272fecd7becc4bc9d557282842e722a4e950940 Author: Yoni Rabkin <yoni@rabkins.net> Date: Wed Aug 4 22:03:56 2010 +0300 * lisp/emms-lastfm-client.el: Make scobbles asynchronous. commit 3981630c588a4ab4226f99ab325dcc97ee9c97ba Author: Yoni Rabkin <yoni@rabkins.net> Date: Wed Aug 4 22:02:29 2010 +0300 * doc/emms.texinfo: Remove because it ain't true no more. commit 8c1b4530b698cb8d439589c1b534246b112444ae Author: William Xu <william.xwl@gmail.com> Date: Sat Jul 17 17:46:34 2010 +0800 (emms-info-track-description): Fix usage of `cond'. commit 1f0070a006311265f096e6d2ba5386c5a1ebcca4 Author: Lucas Bonnet <lucas@rincevent.net> Date: Mon Jul 12 20:41:09 2010 +0200 * lisp/emms-info-ogg.el and lisp/ogg-comment.el: Since emms-info-ogg.el no longer uses ogg-comment, and since it breaks on accents, we can safely remove them, emms-info-ogginfo.el is a working replacement. commit 343468c49f63db71398088aab9981e68b8e683f5 Author: William Xu <william.xwl@gmail.com> Date: Mon Jul 12 02:17:38 2010 +0800 Support displaying lyrics in a dedicated buffer, to highlight playing lyric. * emms-lyrics.el/emms-lyrics-display-buffer: New var. emms-lyrics-buffer: New var. (emms-lyrics-toggle-display-buffer): New func. (emms-lyrics-create-buffer): New func. (emms-lyrics-start): Call `emms-lyrics-create-buffer'. (emms-lyrics-set-timer): Store corresponding LINE number in emms-lyrics-timers. (emms-lyrics-display-handler): Add new arg -- LINE; emms-lyrics-scroll-p's taking effect also depends on emms-lyrics-display-on-modeline. (emms-lyrics-display): Add new arg -- LINE; highlight playing lyric line in emms-lyrics-buffer. (emms-lyrics-scroll): Add new arg -- LINE. * NEWS: Support displaying lyrics in a dedicated buffer, to highlight playing lyric. Thanks to Fang Lungang for the initial patch. commit d5809a45b5f720b3518ad315741a711904e78599 Author: Tim Landscheidt <tim@tim-landscheidt.de> Date: Thu Jul 8 11:47:04 2010 +0000 emms-info-track-description: Handle title-only tracks and fix documentation. * lisp/emms-info.el: Handle tracks without artist, but with title information gracefully and fix documentation. commit 7121df96f2a8ad129de7ec105cd16dc314eee7bc Author: Tim Landscheidt <tim@tim-landscheidt.de> Date: Thu Jul 8 00:41:25 2010 +0000 Fix typos. * lisp/emms-i18n.el: Fix typos. commit f2f57ca971ab2a276d18404ec693155b84a85a5d Author: Tim Landscheidt <tim@tim-landscheidt.de> Date: Wed Jul 7 19:20:32 2010 +0000 Documented emms-playlist-mode-last independently. * doc/emms.texinfo: Documented emms-playlist-mode-last independently following the example of other `pairs' of functions. commit 12e8eb874abd1d0c61be271744cbc894a637430c Author: Tim Landscheidt <tim@tim-landscheidt.de> Date: Wed Jul 7 14:50:55 2010 +0000 Fix typos and spacing. * README, lisp/emms.el: Fix typos and spacing. commit e3f8b5c37ea6ac67e21929a868e14c15dfe4785b Author: Yoni Rabkin <yoni@rabkins.net> Date: Fri Jul 2 09:45:24 2010 +0300 Update emms-lastfm-client.el (code + manual). commit 1315a52925472a0986f8202571796d76008d7f64 Author: Tim Landscheidt <tim@tim-landscheidt.de> Date: Tue Jun 29 14:19:24 2010 +0000 Fix typo. * emms-print-metadata.1: Fix typo. commit c92da9a0c269c046433c427caafb175cb250de94 Author: Lucas Bonnet <lucas@rincevent.net> Date: Tue Jun 29 09:03:34 2010 +0200 From: Dimitry Gashinsky <dimitry@gashinsky.com> * emms-player-vlc.el (define-emms-simple-player): Change the command line arguments from two to one. * emms-player-vlc.el (emms-player-vlc-start): Use the variables that are defined earlier commit da9f87ffd68f7b63843da2910d94281b41f18984 Author: Tim Landscheidt <tim@tim-landscheidt.de> Date: Sun Jun 27 17:33:35 2010 +0000 Fix typos and spacing. * AUTHORS, FAQ, NEWS, README, lisp/emms-bookmarks.el, lisp/emms-cache.el, lisp/later-do.el: Fix typos and spacing. commit ed6a77997d4228d6a6a3da1a880e7672a2853829 Author: Tim Landscheidt <tim@tim-landscheidt.de> Date: Sun Jun 27 15:50:10 2010 +0000 Replace ``?\ '' with ``?\s''. * lisp/emms-browser.el: Replace ``?\ '' with ``?\s''. commit be4a5ae1733ef62c74395640ba7ec30a6c62fdd8 Author: Tim Landscheidt <tim@tim-landscheidt.de> Date: Sun Jun 20 20:54:09 2010 +0000 Align whitespace with original FSF license. * COPYING: Aligned with <URI:http://www.gnu.org/licenses/gpl-3.0.txt>. commit 02020c502e168f89b69a4c1a52b84390b5d15e0e Author: Tim Landscheidt <tim@tim-landscheidt.de> Date: Thu Jun 24 13:03:49 2010 +0000 lisp/emms-lastfm-client.el: Removed Emacs local variable. * lisp/emms-lastfm-client.el: Removed "show-trailing-whitespace: t". This gave a security warning in Emacs and is probably better handled in Emacs' user configuration and/or a Git pre-commit hook. commit 3065ff07817140207222ba963ca448847e53a9f9 Author: Tim Landscheidt <tim@tim-landscheidt.de> Date: Sun Jun 20 20:21:36 2010 +0000 Removed support for gstreamer. * NEWS: Updated. * gst-wrapper: Removed. * lisp/emms-player-simple.el: Removed `(define-emms-simple-player gstreamer)'. commit 8cfc6322cac44d77599a93fcd03fc5c30cda7185 Author: Tim Landscheidt <tim@tim-landscheidt.de> Date: Sun Jun 20 19:40:25 2010 +0000 Fix Texinfo error. * doc/emms.texinfo: Replace `@w' with `@w{}' to allow build of DVI, PDF & Co.; the info output doesn't change. commit a4d7a62c0fc38ef5ce7b1b68f493b552d835214f Author: Lucas Bonnet <lucas@rincevent.net> Date: Tue Jun 15 10:14:38 2010 +0200 * Makefile: autoloads/dist hiccups Thanks to Tim Landscheidt <tim@tim-landscheidt.de> for the patch. commit 3a419dd3a881e798a54d13e0eaa06fd8633e3e05 Author: Lucas Bonnet <lucas@rincevent.net> Date: Tue Jun 15 10:11:04 2010 +0200 * emms-info-libtag.el: Make use of emms-info-libtag-program-name Thanks to Tim Landscheidt <tim@tim-landscheidt.de> for the patch commit 4703c7e690fcd1cef6b16f6b18031ce7297bd007 Author: Yoni Rabkin <yoni@rabkins.net> Date: Mon Jun 14 20:17:37 2010 +0300 * lisp/emms-lastfm-client.el: Add Tim Landscheidt's fixes. commit 625a44279de606b9092e73885ac37b743e0095fa Author: Lucas Bonnet <lucas@rincevent.net> Date: Mon Mar 29 21:35:37 2010 +0200 * Makefile: use taglib-config to get cflags and lib flags source: http://paste.lisp.org/display/97028 commit 8464295b48cec14a29a934877f330de5e9d3e8d0 Author: Yoni Rabkin <yoni@rabkins.net> Date: Sat Mar 27 21:35:22 2010 +0300 * lisp/emms-setup.el: Move emms-mark and emms-tag-editor to emms-all. commit b35aa43c5748914ae5c83c023e0bdd565f59b5af Author: Yoni Rabkin <yoni@rabkins.net> Date: Sat Mar 27 13:27:13 2010 +0300 * doc/emms.texinfo: Document emms-bookmarks. commit ffdceffcafacd5802bbebeb49efd31afa87f24b7 Author: Yoni Rabkin <yoni@rabkins.net> Date: Sat Mar 27 13:26:48 2010 +0300 * lisp/emms-setup.el: Move emms-bookmarks to emms-all. commit 863209bd576a26b9bf0c5ce41710ebd97d5cb80d Author: Yoni Rabkin <yoni@rabkins.net> Date: Sat Mar 27 13:13:52 2010 +0300 * doc/emms.texinfo: Whitespace cleanup. commit 5cd82871a369b39b1d2263ff44f5d4ce77395ec1 Author: Yoni Rabkin <yoni@rabkins.net> Date: Sat Mar 27 13:12:16 2010 +0300 * doc/emms.texinfo: Update copyright years. commit 3108a51bf672d8c07b1f9127715ed526b3474deb Author: Yoni Rabkin <yoni@rabkins.net> Date: Sat Mar 27 13:07:19 2010 +0300 * lisp/emms-setup.el: Move emms-last-played to emms-all. commit b615e5915408201424f7189624176d54bd2ff6b8 Author: Yoni Rabkin <yoni@rabkins.net> Date: Sat Mar 27 13:00:02 2010 +0300 * lisp/emms-lastfm-client.el: Update copyright years. commit 10e69b66ac796facd269b553b8399603db209290 Author: Yoni Rabkin <yoni@rabkins.net> Date: Sat Mar 27 12:59:45 2010 +0300 Document emms-lastfm-client.el commit a0d2b12db99805d4120bb06f205f57af5777e016 Author: Yoni Rabkin <yoni@rabkins.net> Date: Sat Mar 27 12:58:25 2010 +0300 * lisp/emms-setup.el: Move emms-lastfm-client to emms-all. commit 4dcb06d6597890337c04b08a88b0fc553cc558e6 Author: William Xu <william.xwl@gmail.com> Date: Fri Mar 19 23:35:59 2010 +0800 Move emms-cue.el from emms-devel to emms-all and update manual. commit 9390fc321a233787dcb2dfc9426f7468c32153bc Author: David Engster <deng@randomsample.de> Date: Wed Mar 10 18:37:30 2010 +0100 lisp/emms-cache.el: Initialize cache immediately instead of using after-init-hook. * emms-cache.el (emms-cache): Call emms-cache-restore directly instead of using after-init-hook. commit 903e2484fa658eef9b4dc8bbd0bf4958f7233242 Author: Lucas Bonnet <lucas@rincevent.net> Date: Thu Mar 4 22:13:48 2010 +0100 * AUTHORS: add David Engster, thanks to his patches for MusicPD. commit 5e6e1f3181550c0c1794acd8ba8f63871d0bcb9b Author: David Engster <deng@randomsample.de> Date: Tue Mar 2 22:00:36 2010 +0100 emms-player-mpd.el: Parsing of supported formats for newer versions of mpd. * emms-player-mpd: (emms-player-mpd-get-supported-regexp): Added code to parse the output of newer versions of mpd. commit 692d1841d1f088dac00737f44ecbf7aca3781317 Author: Lucas Bonnet <lucas@rincevent.net> Date: Mon Mar 1 18:30:31 2010 +0100 * emms-player-mpd: (emms-player-mpd-seek, emms-player-mpd-seek-to): Round to full seconds since mpd doesn't allow float values for seeking (this usually happens with emms-cue-next, for instance). Patch by David Engster <deng@randomsample.de> commit 886bfe0593e5ba0f419e499b8112cf4bb6b39679 Author: Lucas Bonnet <lucas@rincevent.net> Date: Fri Feb 26 18:01:21 2010 +0100 * lisp/emms-player-mpd.el: new function to update all MPD tracks, then clear local cache and fetch new updated cache from MusicPD Patch by David Engster <deng@randomsample.de> commit 8d104889afa240aa69a09124837bde832d955941 Author: Lucas Bonnet <lucas@rincevent.net> Date: Mon Feb 22 20:09:04 2010 +0100 * .gitignore: update emms-print-metadata path commit 874a92b55ccd177557cee15dad9a4572bc84dd8f Author: Lucas Bonnet <lucas@rincevent.net> Date: Mon Feb 22 20:08:08 2010 +0100 * lisp/emms-player-mpd.el (emms-player-mpd-add): do not add files not recognized by MPD Patch by David Engster <deng@randomsample.de> commit cf3b4a73e3ee05b0a4e4cd03e5da481da0466a8f Author: Lucas Bonnet <lucas@rincevent.net> Date: Fri Feb 19 16:38:24 2010 +0100 * lisp/emms-source-file.el: Avoid adding duplicates when dealing with symbolic link. Patch from Stefan Kangas <skangas@skangas.se> commit 138e646969facc2b8c1527cb249dcef64ec2051b Author: Yoni Rabkin <yoni@rabkins.net> Date: Thu Dec 24 21:32:20 2009 +0200 * lisp/emms-setup.el: Replace the `emms-lastfm' feature. commit ea7d3100b660201ff5e24d3c53cb403f23b09786 Author: Yoni Rabkin <yoni@rabkins.net> Date: Thu Dec 24 21:30:32 2009 +0200 Replace lisp/emms-lastfm.el with lisp/emms-lastfm-client.el. The original emms-lastfm.el doesn't work at all with the current Last.fm API. commit 731ac90ef70b6e9874a396f0c69dbf8be2fff83f Author: William Xu <william.xwl@gmail.com> Date: Thu Dec 24 20:23:55 2009 +0800 emms-browser-top-level-type: Fix typo. commit 90f3ed8450328cdf5677458bde6cab872f547461 Author: William Xu <william.xwl@gmail.com> Date: Fri Nov 27 21:54:46 2009 +0800 emms-cue.el (emms-info-cueinfo): New function for retrieving track info. - (emms-cue-next-track): Replace find-file-noselect with emms-insert-file-contents. - emms-setup.el: Add emms-info-cueinfo to emms-info-functions. commit e54c755ce0c2ef19bfcd4cdca995e4d2bc3b2703 Author: William Xu <william.xwl@gmail.com> Date: Mon Nov 23 22:11:19 2009 +0800 Fix compiler warnings. For emms-browser.el, emms-compat.el, emms-last-play.el, emms-lyrics.el and emms-streams.el. commit 2b629e9c2d97a521a4cddbf03286661eab687c42 Author: William Xu <william.xwl@gmail.com> Date: Mon Nov 23 21:27:45 2009 +0800 emms-cue.el: New file. emms-setup.el: Enable emms-cue and emms-mode-line-icon modules. commit f605bbf41320f867614b2c56891b10986e405839 Author: William Xu <william.xwl@gmail.com> Date: Sun Nov 22 21:38:22 2009 +0800 (emms-playing-time-display): Gurantee emms-playing-time to be an integer. commit eef8a91d50aa4515daec4cd51ef8a1e0a3682a75 Author: William Xu <william.xwl@gmail.com> Date: Thu Aug 6 18:53:19 2009 +0800 emms-i18n.el: Spell fix. commit 3e001aacb45633583282001d49634e080deaf8d7 Author: Yoni Rabkin <yoni@rabkins.net> Date: Wed Aug 5 21:47:28 2009 +0300 * lisp/emms-playlist-mode.el: (emms-playlist-mode-open-buffer) Use `emms-insert-file-contents' to load saved playlist. commit 2c1c56d553df6ee1973134fdb90543454b1146ca Author: Michael Olson <mwolson@gnu.org> Date: Wed Aug 5 08:07:03 2009 -0700 Introduce emms-insert-file-contents. This function is a safe way to insert the contents of a file without triggering major mode detection, and has been tested on several versions of Emacs and XEmacs. commit 97344c85a0657e479177620daa5b3bdc956e31fb Author: William Xu <william.xwl@gmail.com> Date: Sat Aug 1 10:40:20 2009 +0800 (emms-player-vlc-start): Around-advice it with `quit-vlc-after-finish' to resolve "function redefined" compile warnings. commit 510f4a8f407f5f62cfb309400c70ef5fc32ced76 Author: William Xu <william.xwl@gmail.com> Date: Sat Aug 1 01:18:29 2009 +0800 (emms-playlist-sort-map-setup): Bind emms-playlist-sort-by-file-extension to "e" in emms-playlist-sort-map. commit 0f88ab3db42dd78f73ae12da933f3b39fbd90411 Author: William Xu <william.xwl@gmail.com> Date: Sat Aug 1 01:12:36 2009 +0800 emms-playlist-sort.el: Refactor sort functions. (emms-playlist-sort-by-file-extension): New func. commit 8176350744ebefe066478bfc3de9a00e34261b77 Author: William Xu <william.xwl@gmail.com> Date: Sun Jul 26 13:45:48 2009 +0800 (emms-history-file-coding-system): New var. (emms-history-save): Set mode and coding-system in saved file. commit 67bcbeb63bd0d73632992d0106524b118a89fd29 Author: Yoni Rabkin <yoni@rabkins.net> Date: Sun Jul 5 08:58:27 2009 +0300 * lisp/emms-playlist-mode.el: Bind "C-x u" to `emms-playlist-mode-undo' in emms-playlist-mode. commit af49e9e173e1be8e95c70fe454f96ca3512461d0 Author: Michael Olson <mwolson@gnu.org> Date: Tue Jun 9 23:27:34 2009 -0700 emms-source-playlist: Docstring typo. commit 6e7b40ad7b322d9dea31e399ce6359d26a191ad6 Author: Michael Olson <mwolson@gnu.org> Date: Tue Jun 9 23:09:06 2009 -0700 emms-source-playlist: Fix bug, update docstring. commit 83234f84ad0420f121797e344dff842b35e38ed0 Author: Dieter Deyke <deyke@yahoo.com> Date: Mon May 25 21:05:54 2009 -0600 Allow relative file names in .m3u playlists commit f4dd5b038324bfef2da338eea70ea32e9947e0e2 Author: Michael Olson <mwolson@gnu.org> Date: Tue Mar 31 09:23:10 2009 -0700 emms-tag-editor: Turn all symbols to strings before completing read. Otherwise ido-mode will choke on it. commit 4b2158e03e8c026760b00c5cc7c4cc6d742bea8f Author: Tassilo Horn <tassilo@member.fsf.org> Date: Mon Mar 16 09:22:29 2009 +0100 Add "ogm" extension to VLC, MPlayer and Xine. commit a1656480c97858ea9c70cf88c098ecaa3be9b85a Author: Yoni Rabkin <yoni@rabkins.net> Date: Tue Mar 10 21:45:13 2009 +0200 * lisp/emms-player-vlc.el: Add support for VLC versions > 0.8.6e. commit f201cdb3786319fbd2b2e4661327ab3e3e1cc677 Author: Jose Antonio Ortega Ruiz <jao@gnu.org> Date: Sun Mar 8 21:50:44 2009 +0100 (emms-browser-mmatches-p): When performing searches, check whether This is the second patch addressing the null track fields issue. In this case, before trying to STRING-MATCH in a search, we check that the track's field is non-null. commit b322d37a92710f8846f7a518a86cc3976825508f Author: Jose Antonio Ortega Ruiz <jao@gnu.org> Date: Sun Mar 8 21:50:43 2009 +0100 * emms-browser.el (emms-browser-make-hash-by): Check that field is present before attempting to add entries. Addresses an issue'm encountered when using lastfm integration and mpd as the player. After requesting streaming from last.fm, a new track gets added to EMMS' database, which is named after the streaming URL but has no other fields. Thus, when adding entries or making searches, checking the the field at hand is non-nil is needed. This patch checks that for emms-browser-make-hash-by. commit c4a18712be3b036a2336db631a534d0e3ce162b9 Author: Lucas Bonnet <lucas@rincevent.net> Date: Tue Feb 17 23:39:56 2009 +0100 * AUTHORS: add Jesse W * doc/emms.texinfo: display the licence commit 9fa028e62643365f1429aeb5d9e985ed81668748 Author: Michael Olson <mwolson@gnu.org> Date: Sun Feb 8 10:00:53 2009 -0800 Update copyright headers. commit 9bfa083a69bf384fc8e70327006f92612dcbe962 Author: Michael Olson <mwolson@gnu.org> Date: Sun Feb 8 09:52:49 2009 -0800 tq.el: Update header. commit 1cb621334a33563996784b14eadc96f2126767f2 Author: Yoni Rabkin <yoni@rabkins.net> Date: Wed Dec 24 19:40:07 2008 +0200 * lisp/emms-stream-info.el: Reimplement using player backends. commit b1e16d0f1d8f8ac13efc3706b016d4abbb06949d Author: Yoni Rabkin <yoni@rabkins.net> Date: Wed Dec 24 07:54:25 2008 +0200 * lisp/emms-stream-info.el Nuke the contents of the old emms-stream-info.el file in preparation for a rewrite. commit 0176b1afe505be41a2af7920aaa8c99dc3d5407d Author: William Xu <william.xwl@gmail.com> Date: Sun Dec 21 15:07:50 2008 +0800 emms-i18n-default-coding-system: Change default value from nil to '(no-conversion . no-conversion). commit fabcafd5e8100e9ac8bb6b68ccc88df3a1309c7a Author: Lucas Bonnet <lucas@rincevent.net> Date: Sun Nov 2 14:50:40 2008 +0100 update Makefile to honor emms-print-metadata changes commit af22d82ed6a660e98a550911257a8397963b2bca Author: Lucas Bonnet <lucas@rincevent.net> Date: Sun Nov 2 14:46:54 2008 +0100 Move emms-print-metadata.c to its own directory commit 608b267e0f8d0c488daf8d7ae6c344ed62857025 Author: Sascha Wilde <wilde@sha-bang.de> Date: Thu Oct 16 10:28:35 2008 +0200 Don't set foreground explicitly to NIL in emms-stream-name-face. This is needed to make emms work with current GNU Emacs CVS HEAD. commit 51bcbfc68ce06e022e727f4e191d5d66f54ce618 Author: Yoni Rabkin <yoni@rabkins.net> Date: Thu Oct 2 18:53:53 2008 +0300 * emms-player-vlc.el: Add support for playlists. Signed-off-by: Yoni Rabkin <yoni@rabkins.net> commit 8fce904cf69a3e4545e77002195cc4613f935736 Author: Yoni Rabkin <yoni@rabkins.net> Date: Thu Oct 2 18:01:50 2008 +0300 * emms-player-vlc.el (emms-player-vlc-seek): Add seek functionality for vlc. * emms-player-vlc.el (emms-player-vlc-seek-to): Add docstring. commit 31841733b197fb4ad41b4270d0669059ad6e88c6 Author: Yoni Rabkin <yonirabkin@member.fsf.org> Date: Tue Sep 30 23:32:21 2008 +0300 Add VideoLAN, aka vlc, support to Emms. * lisp/emms-player-vlc.el: Add new file emms-player-vlc.el with preliminary support for vlc. * lisp/emms-setup.el: (emms-setup-default-player-list) Add the emms-player-vlc player. (emms-minimalistic) Add emms-player-vlc as a requirement. commit bd8bb8af89086bbf336c7890813e2a35a3349525 Author: Michael Olson <mwolson@gnu.org> Date: Sat Sep 20 11:10:27 2008 -0700 Update RELEASE info, generate ChangeLog when making release. commit 9f076337372d7db84accf7b57f3f3af1dceda61f Author: Michael Olson <mwolson@gnu.org> Date: Sat Sep 20 11:02:18 2008 -0700 emms-print-metadata: Update copyright years. commit 36f986dcbf09ed774dadb86fe78cbca248c5b025 Author: Michael Olson <mwolson@gnu.org> Date: Sat Sep 20 10:58:36 2008 -0700 Update copyright lines. Also, - Force utf-8 encoding in all files. - Update header of tq.el from version in Emacs. commit c5bf649d13f04bf2e22a548163b971f3fbf74b1b Author: Michael Olson <mwolson@gnu.org> Date: Sat Sep 20 10:33:29 2008 -0700 Clean up use of regexps to match supported tracks. * lisp/emms-player-mpd.el (emms-player-mpd-supported-regexp): Use emms-player-simple-regexp. * lisp/emms-player-mplayer.el (mplayer): Ditto. (mplayer-playlist): Only match http:// at beginning of filename. * lisp/emms-player-simple.el (mikmod, alsaplayer): Don't put periods in extensions. Separate URLs from extensions. * lisp/emms-player-xine.el (xine): Use emms-player-simple-regexp. * lisp/emms-source-playlist.el (emms-source-playlist-parse-m3u) (emms-source-playlist-parse-pls): Make regexp easier to read. commit ba8b47960a5722d28ada46d850a9272cd5482a66 Author: Michael Olson <mwolson@gnu.org> Date: Fri Sep 19 21:35:17 2008 -0700 emms-tag-editor: Fix compiler warning. commit 99c433e442aac0a9ef40f45089b8a57136a061c3 Author: Michael Olson <mwolson@gnu.org> Date: Fri Sep 19 21:29:17 2008 -0700 emms-source-playlist: Remove unused helper functions. * lisp/emms-source-playlist.el (emms-source-playlist-first) (emms-source-playlist-next): Remove. commit dad93593e3efff45f182ba8292063163c73e3e7f Author: Michael Olson <mwolson@gnu.org> Date: Fri Sep 19 21:27:06 2008 -0700 emms-source-playlist: Fix several bugs. * lisp/emms-source-playlist.el (emms-source-playlist-read-format): Make sure that the history has the complete format name. (emms-source-playlist-unparse-native) (emms-source-playlist-unparse-m3u) (emms-source-playlist-unparse-pls): Rewrite to use emms-walk, because that is easier to reason about. This fixes a bug where only the last half of a particular playlist was being written out. commit aba7314b193d45a0ac0b6e44a8c2d860178a7c5e Author: Michael Olson <mwolson@gnu.org> Date: Thu Sep 18 22:32:07 2008 -0700 emms-player-mpd: Allow periodic song-change timer to be suppressed. * lisp/emms-player-mpd.el (emms-player-mpd-check-interval): Allow this to be nil. (emms-player-mpd-play): If nil, do just one check, so that we can record the current play/paused state. (emms-player-mpd-connect-1): If nil, don't install the timer. commit 56a0223179942c6a7f8f90bf7c26922638ccb304 Author: Michael Olson <mwolson@gnu.org> Date: Wed Sep 17 11:19:35 2008 -0700 Makefile: Generate autoloads before compiling source. This makes compilation warnings in the source easier to spot, and mirrors the behavior of Emacs itself. commit 71cec79f643194d19b48d20574a37b1489274833 Author: Michael Olson <mwolson@gnu.org> Date: Tue Sep 16 07:33:08 2008 -0700 Check in .gitignore file. commit fec94b813d20d571a7cf69a9c7913c889160583d Author: Tom Rauchenwald <its.sec@gmx.net> Date: Mon Sep 15 20:57:29 2008 -0700 emms-info-libtag: Ignore taglib warnings. commit 736863e830b8feeae20425c73b2285da9162f662 Author: Michael Olson <mwolson@gnu.org> Date: Sun Sep 14 19:02:31 2008 -0700 Makefile: Add targets for making releases and uploading them. commit 376b9ebede6cc8c6fbcd3d2ececaa7311d67a973 Author: Yoni Rabkin <yonirabkin@member.fsf.org> Date: Tue Sep 2 20:46:14 2008 +0300 Ask before saving over an existing playlist file. As suggested on the mailing list, this feature can be turned off. The appropriate documentation has been added to the Emms manual. Signed-off-by: Yoni Rabkin <yonirabkin@member.fsf.org> commit 7b3d06420b46ec37d6d0c033f04b0a9c50717fa8 Author: Yoni Rabkin <yonirabkin@member.fsf.org> Date: Fri Aug 29 16:40:53 2008 +0300 Prevent interactive yanking from messing up the playlist buffer. Usually, emms-playlist-mode tries not to alter the standard Emacs editing behavior, so that killing and yanking work exactly like they would everywhere else in Emacs. But having two Emms tracks in the emms-playlist-mode buffer on the same line doesn't make sense. This should stop yank commands from doing that. Signed-off-by: Yoni Rabkin <yonirabkin@member.fsf.org> commit 36b3d963b1ff780914a7e690a34cd0ba3a65043a Author: Michael Olson <mwolson@gnu.org> Date: Sat Aug 9 13:29:20 2008 -0700 emms-lastfm: Mention emms-play-lastfm-artist-fan in header. commit afa5c8cc95dc940386fd4e2065b8dac19b72d587 Author: Michael Olson <mwolson@gnu.org> Date: Sat Aug 9 13:23:28 2008 -0700 emms-lastfm: Complete artist names from cache. * doc/emms.texinfo: Update copyright years. (Last.fm radio): Update names of functions. * lisp/emms-lastfm.el (emms-lastfm-read-artist): New function that reads an artist from the user, doing completions from the EMMS track cache if present. (emms-play-lastfm-similar-artists): Rename from emms-lastfm-radio-similar-artists. Use completion. Thanks to Thierry Volpiatto for the initial implementation (emms-play-lastfm-global-tag): Rename from emms-lastfm-radio-global-tag. (emms-play-lastfm-artist-fan): Rename from emms-lastfm-radio-artist-fan. Use completion. commit c6a98ba99332e8398f58afad0116e0018882514b Author: Michael Olson <mwolson@gnu.org> Date: Fri Aug 8 09:29:30 2008 -0700 emms-lastfm: Fix timer issue when playing radio station. * lisp/emms-lastfm.el (emms-lastfm-radio-sentinel): Cancel the timer only after emms-player-started-hook is called. Make sure existing timer is canceled before starting new one. Thanks to Thierry Volpiatto for the initial code. (emms-lastfm-cancel-timer-after-stop): New barebones function to add to emms-player-started-hook. (emms-lastfm): Remove it from emms-player-started-hook. commit cf588f5ea96b7523965ac48bc39e6d9d2dc4e828 Author: Michael Olson <mwolson@gnu.org> Date: Fri Aug 8 08:59:56 2008 -0700 Introduce emms-completing-read. This allows users to specify which completing-read function to use, defaulting to ido-completing-read. The relevant option is emms-completing-read-function. Thanks to Thierry Volpiatto for the idea. commit 616f160c7f783dc232f68ea6ab8b40a36f690b18 Author: Michael Olson <mwolson@gnu.org> Date: Thu Aug 7 23:17:55 2008 -0700 Implement filtering of track data after retrieving it. * lisp/emms.el (emms-track-info-filters): New option that allows the user to specify some functions that filter track data. One example of this is removing cruft like "(Album Version)" from music purchased over Amazon without having to edit every single music file. (emms-track-updated-functions): Update docstring to indicate that this is called after display of the track, not before. (emms-track-updated): Call emms-track-info-filters. * lisp/emms-player-mpd.el (emms-player-mpd-get-tracks-1) (emms-player-mpd-show-1): Call emms-track-info-filters. commit 96924d99f35234cf6de2a49574d792d5147423d4 Author: Michael Olson <mwolson@gnu.org> Date: Thu Aug 7 22:11:29 2008 -0700 emms-playlist-mode: Use "EMMS" in mode-line. * lisp/emms-playlist-mode.el (emms-playlist-mode): Use "EMMS" in the mode-line, not the long "Emms-Playlist". This pretty much *is* the essence of EMMS now. commit 3c8448d655e701d42ce6c0fcdd4a9438eb5d3b67 Author: Yoni Rabkin <yonirabkin@member.fsf.org> Date: Fri Aug 1 17:29:21 2008 +0300 emms.texinfo: New advocacy section in the manual titled "Formats and Freedom". commit 29d95518de8c3bfc8f00e7fe70acf41fbe8381e8 Author: Michael Olson <mwolson@gnu.org> Date: Thu Jul 17 01:40:23 2008 -0700 emms-player-mpd: Fix compiler warning. commit d9e91adaff80faf0df2fc1f9199cc9f613bc1c98 Author: Michael Olson <mwolson@gnu.org> Date: Thu Jul 17 01:38:59 2008 -0700 tq: Disable undo. commit a31cdb0104a6ee08761cdca69c31f3671205ac30 Author: Michael Olson <mwolson@gnu.org> Date: Wed Jul 16 23:30:59 2008 -0700 emms-player-mpd: Only try once to read tracks after running out of them. This fixes a bug introduced in the last commit. commit 50dab1d731182939f48ff2c5196c98499c4103a1 Author: Michael Olson <mwolson@gnu.org> Date: Wed Jul 16 23:06:27 2008 -0700 emms-player-mpd: Implement handling of non-EMMS stop of mpd. * lisp/emms-player-mpd.el (emms-player-mpd-last-state): New variable. (emms-player-mpd-detect-song-change-2): New function that triggers playing time update after a non-EMMS-triggered stop. (emms-player-mpd-detect-song-change-1): Do not disconnect on stop. Implement handling of the case where people run "mpc stop", "mpc start" manually. Have EMMS pick up from where they left off. (emms-player-mpd-clear): Trigger the removal of playing time from the modeline. (emms-player-mpd-disconnect): Clear emms-player-mpd-last-state. commit c0b02ba11520f1bd3f1b419ebc689bb07f0b4133 Author: Yoni Rabkin <yonirabkin@member.fsf.org> Date: Sat Jul 5 10:38:09 2008 +0300 Update the Emms manual to point to the newly added lisp/ directory. Signed-off-by: Yoni Rabkin <yonirabkin@member.fsf.org> commit ef3300d01073ec67b2daea9e9d2553d378150858 Author: William Xu <william.xwl@gmail.com> Date: Tue Jun 17 18:30:31 2008 +0900 (emms-pause): If player hasn't started, then start it now. commit 67f5263943276faee0de53d947b6191205ae7a43 Author: William Xu <william.xwl@gmail.com> Date: Tue Jun 17 14:43:45 2008 +0900 *.el -> lisp/*.el: Move lisp files into "lisp/" subdirectory. commit 964d7c3b354b66d0fba6f4eb7c2e058c2bfe2d59 Author: Michael Olson <mwolson@gnu.org> Date: Mon Jun 16 20:42:30 2008 -0700 doc/gpl.texi: Remove trailing whitespace. commit 0642030ce328850db198cc0134bdac6a5fdd041e Author: Yoni Rabkin <yoni@rabkins.net> Date: Mon Jun 16 18:45:37 2008 +0300 Emms directory structure change/cleanup I've been thinking about moving some parts of Emms to their own directories in order to tidy up the distribution. Attached is a patch which does this for the documentation. What do you people think? >From 61459ce16456b31b119faefc6333007a023436d5 Mon Sep 17 00:00:00 2001 From: Yoni Rabkin <yonirabkin@member.fsf.org> Date: Thu, 8 May 2008 23:58:07 +0300 Subject: [PATCH] Moved Emms documentation to a newly created doc directory. As a first step in cleaning up the Emms distribution directory structure, I've moved all the documentation to its own directory. Makefiles have been created/updated accordingly. Signed-off-by: Yoni Rabkin <yonirabkin@member.fsf.org> commit 8a45d190bfc5e4728f2bcab5674636c0779f7074 Author: Tassilo Horn <tassilo@member.fsf.org> Date: Mon Jun 16 21:35:57 2008 +0200 Make emms-lastfm-protocol-version a constant and fix a typo. commit 86a830f81a2688428ac03e0e4733866ff79b7e12 Author: Michael Olson <mwolson@gnu.org> Date: Wed Jun 4 07:10:44 2008 -0700 emms-player-mpd.el: Quote argument to "update" command. commit bbefa2ae801843625389a80b7b28c7e579fab96d Author: Ye Wenbin <wenbinye@gmail.com> Date: Sat May 3 15:09:00 2008 +0000 Get and set Flac file tags darcs-hash:20080503150900-94065-f674212fe81666e233d381462fbe3bd1f67f9eae.gz commit 84976d82cfda6fac3af21b1e1b0df81c2136c80b Author: William Xu <william.xwl@gmail.com> Date: Wed Apr 16 16:05:00 2008 +0000 (emms-sort-natural-order-less-p): Handle empty 'info-album(treat as "" when sorting) correctly. darcs-hash:20080416160530-cfa61-de44c3dd75d0a5a75111ea1c544e457408bed594.gz commit bc41b9789b270cad9376e961fd6195d3e31fa9b5 Author: William Xu <william.xwl@gmail.com> Date: Wed Apr 16 15:58:00 2008 +0000 (emms-playlist-sort): Remove region arguments. (It didn't used to work anyway...) Restore track sequence reversed by emms-playlist-tracks-in-region. (emms-string<, emms-string>): Default nil element to "". darcs-hash:20080416155820-cfa61-32bfe6019096e32bec7fa404145f65186f3c51cb.gz commit f57b1526ff9219b70f6de29b5808257750b2ae0c Author: William Xu <william.xwl@gmail.com> Date: Tue Apr 15 17:21:00 2008 +0000 - emms-playlist-sort-prefix, emms-playlist-sort-map: New variable. (emms-playlist-sort-map-setup): New function. Restore codes for customizing sort map prefix keys. - (emms-playlist-sort): Bug fix. - (emms-playlist-sort-by-score): Removed. (emms-playlist-sort-by-play-count, emms-playlist-sort-by-last-played): New functions. Remove all emms-score related codes, since basically its functionality is replaced by emms-last-played's play-count feature, with more simple & clean implementation. - Most sort functions now accepts an additional prefix argument for sorting reversely. darcs-hash:20080415172119-cfa61-128afe3b1f51c8a79fe01cf631f21d611e84f479.gz commit e2ec2bc4735bc7224e2a1316388e3ad76be6e129 Author: William Xu <william.xwl@gmail.com> Date: Tue Apr 15 06:39:00 2008 +0000 (emms-playlist-mode-go-popup): `round' emms-playlist-mode-window-width to be an integer, so that split-window-horizontally won't complain even if user provides a floating point. darcs-hash:20080415063957-cfa61-c3b7269628cbf31c699c5650f61fc28d42fd0b3d.gz commit d876bd1443c85f10f6da318f19e9619d04204ea7 Author: William Xu <william.xwl@gmail.com> Date: Sun Apr 6 14:46:00 2008 +0000 emms-lyrics-coding-system: Change default value to nil and update docstring. This change will allow us to use lyrics files encoded with different coding systems. darcs-hash:20080406144623-cfa61-7109bbc9b6c370932989103f2f807ec76eb622d6.gz commit fb73b8713841d417d8b9e6c40e97f38e301053f4 Author: Ye Wenbin <wenbinye@gmail.com> Date: Thu Apr 3 04:58:00 2008 +0000 Fix bug of missing lyrics Note that sort is a destructive function, so the value should store back after sort. darcs-hash:20080403045858-94065-7b772d23b118d68193939433d0c4cd00a102589b.gz commit c7e297ecff6ce3e4baf3957345f6e18c245d8507 Author: William Xu <william.xwl@gmail.com> Date: Tue Apr 1 13:23:00 2008 +0000 Remove codes for loading movie subtitles automatically by emms. darcs-hash:20080401132338-cfa61-ae5d461981ce3f3470d2a21a4a6acf94e448ea78.gz commit ed66137edc089844ccc8162d09a259e5acf7c32d Author: William Xu <william.xwl@gmail.com> Date: Tue Apr 1 13:22:00 2008 +0000 Remove codes for loading movie subtitles automatically by emms, since mplayer has an option(`sub-fuzziness') controlling that. (emms-player-mplayer-subtitle-checker, emms-player-mplayer-start-with-subtitle-checker): Removed. emms-player-mplayer-subtitle-extensions: Removed. darcs-hash:20080401132242-cfa61-0c70393c1b4b4263e1d5afec5134c947d6659dab.gz commit 0d86b1844c9173c24889896c0531c75973b75e57 Author: William Xu <william.xwl@gmail.com> Date: Sat Mar 15 09:28:00 2008 +0000 (emms-player-mplayer-subtitle-checker): Replace (lambda (el) el) with a simpler function -- `identify'. darcs-hash:20080315092854-cfa61-d185513e398b57d9a0550bca96441bdc1ec30598.gz commit 0c0fe3d567921db68464b6bfd9b24cc9d4093f6c Author: yoni <yoni> Date: Tue Feb 19 12:51:00 2008 +0000 Switched the keybinding for "d" and "D" so that they agree with the browser. darcs-hash:20080219125135-670cc-f0fb9a14f55eb476f9699089f44c537abb5ca5bb.gz commit 71e9dc9e84d9e22c5ca891a1883a160882b73d5f Author: William Xu <william.xwl@gmail.com> Date: Sat Mar 1 15:15:00 2008 +0000 emms-lyrics.el, emms.texinfo: Remove "Known Problems" note, as it looks fairly okay. darcs-hash:20080301151546-cfa61-2ffa91603ff4f1c4b99de762e12412f62db69827.gz commit bb46e7695549d207cc00ca216286d1b634f811ee Author: William Xu <william.xwl@gmail.com> Date: Fri Feb 22 09:13:00 2008 +0000 mplayer,xine: Replace regexp-opt with simple regexp-quote, to avoid using regexp-opt's shy group regexp feature, so that external "find" can work properly. darcs-hash:20080222091303-cfa61-6d3979b424b933da1e6696a9538389614eab13b6.gz commit c5281105e8b39e7f73404f6b22148845d9c78c9b Author: Michael Olson <mwolson@gnu.org> Date: Thu Feb 21 06:37:00 2008 +0000 Fix compiler warnings about mapcar. darcs-hash:20080221063736-1bfb2-413a3e0ba2ea79c693651e5b8e5d61c2a790fcd5.gz commit 9867a7128473f1df9b718571603028af9c59c135 Author: yoni <yoni> Date: Sat Feb 16 11:59:00 2008 +0000 Added emms-playlist-mode-goto-dired-at-point (with keybinding) to emms-playlist-mode.el. darcs-hash:20080216115915-670cc-d188de0d0a8b74d0f21313f061d89c90e8cde09f.gz commit c932d7f13c696b3ebf36f20ac43564ad99e7a96e Author: yoni <yoni> Date: Fri Feb 15 17:21:00 2008 +0000 Lines in playlist-mode should truncate so that visually we have 1 line per track. darcs-hash:20080215172145-670cc-db48df0e9f029a81da7a559ae453f29a36716e8e.gz commit db742d675bfd2422fa8b3e597c46f8cbd275b29a Author: William Xu <william.xwl@gmail.com> Date: Sat Feb 16 09:00:00 2008 +0000 (emms-lastfm-submit-now-playing): Set track-length to 0 when info-playing-time is unset, so that `number-to-string' won't raise an error. darcs-hash:20080216090004-cfa61-62ea04a64f023407b119cd47318b9edde87e2b70.gz commit 5198c20b9fe58a7a167078b2aea1e952585dd268 Author: William Xu <william.xwl@gmail.com> Date: Sat Feb 16 08:56:00 2008 +0000 (emms-url-quote): Check validity of string parameter S. darcs-hash:20080216085614-cfa61-7ff36e17d340cb138941a82f5e90c8077a3868eb.gz commit 3294650f52d5a1ac41fb933fade5b46753ed13f1 Author: William Xu <william.xwl@gmail.com> Date: Sat Feb 16 04:31:00 2008 +0000 (emms-url-quote): Slightly rewrote to be more readable. Fix docstring typo. darcs-hash:20080216043149-cfa61-d40e96954a985f13ea81f618aef396cff7037363.gz commit 2964c94e715085829002ded00cc9933cf4b2279c Author: Michael Olson <mwolson@gnu.org> Date: Fri Feb 15 17:35:00 2008 +0000 emms-url: Add emms-url-quote-entire function. Use it to conservatively escape entire URLs. Make emms-player-mpd use this instead of emms-url-quote. darcs-hash:20080215173509-1bfb2-de02bb833c0ca4afefa42f232c1278d1c3e155ca.gz commit 4ff658089418170cc4628effc3481b6ec0f01dd2 Author: Michael Olson <mwolson@gnu.org> Date: Fri Feb 15 17:32:00 2008 +0000 emms-url: Revert most of last two changes. Change remaining: Save match data. New changes: Update documentation to mention that this is only meant to be used for parts of URLs, not entire URLs. darcs-hash:20080215173207-1bfb2-916f0f32a5bc31190dcb91ac9d52a3b503835cad.gz commit c0ea2609fc6c3e26047f4b9d10dc04348b60719c Author: Michael Olson <mwolson@gnu.org> Date: Fri Feb 15 05:01:00 2008 +0000 emms-url: Include forward slashes in URL regexp. darcs-hash:20080215050112-1bfb2-ab58d7205a9dc94b780e463d69a946e9bc2cdc06.gz commit 6f8dc64b8d9b65887a29a0f94705cbf9ac2bf631 Author: Michael Olson <mwolson@gnu.org> Date: Fri Feb 15 02:58:00 2008 +0000 emms-url: Improve emms-url-quote. - Don't clobber the match data. - Don't escape the colon in "http://". darcs-hash:20080215025800-1bfb2-ad6899b9c1134c782a1fab2ca206e158d62042e3.gz commit 535f7f7bf8ca34162b3ad854576d78ebf3ffb480 Author: William Xu <william.xwl@gmail.com> Date: Tue Feb 12 10:39:00 2008 +0000 Resolve conflicts with Tassilo's repo. darcs-hash:20080212103958-cfa61-4b529ef427982120e33ca7660dcfc3d3584f8196.gz commit eb4229b372252d0e709760edcfc1ffe759367b70 Author: William Xu <william.xwl@gmail.com> Date: Tue Feb 12 06:48:00 2008 +0000 - emms-url.el: (emms-url-quote, emms-url-quote-plus), New functions renamed from emms-lyrics-url-quote, emms-lyrics-url-quote-plus defined in emms-lyrics.el. - emms-url.el: (emms-escape-url, emms-url-specials), deleted, since they can only escape ASCII characters, emms-url-quote can handle all characters. - Update affected files accordingly. darcs-hash:20080212064822-cfa61-759d28b271024ab1a17bd23a2444c076d04e55e7.gz commit 5f0591f7fe91bda35c44faa4134870a2296a9d5e Author: William Xu <william.xwl@gmail.com> Date: Tue Feb 12 04:12:00 2008 +0000 (emms-lastfm-radio-request-metadata-sentinel): Let `emms-track-updated' take care of updating track info. darcs-hash:20080212041204-cfa61-b9e5ee5ad4e09a6ebe583e796e573abd18b0afa3.gz commit 01efb7c0a107cc5412e895460b2630d33968a23d Author: Tassilo Horn <tassilo@member.fsf.org> Date: Tue Feb 12 09:05:00 2008 +0000 abstract-POST-and-GET-requests-in-own-functions.dpatch darcs-hash:20080212090550-c06f4-dd27baa19380749860d161494177a8a2ddc0f077.gz commit bef69ae0d482d5782f2370133809bcc2b62d1e15 Author: Tassilo Horn <tassilo@member.fsf.org> Date: Mon Feb 11 14:15:00 2008 +0000 add-todo-comment.dpatch darcs-hash:20080211141544-c06f4-a2b39ee7c2030e1ec38232e59e9893701db27bb9.gz commit 1464bb8555611e3cea799f1f6c283acd1e0b14db Author: Tassilo Horn <tassilo@member.fsf.org> Date: Mon Feb 11 12:12:00 2008 +0000 add-support-for-now-playing-infos-on-lastfm-page.dpatch darcs-hash:20080211121258-c06f4-9195c81ac69c0c4d30b2fc271dcfcbbbe77ad1fc.gz commit ba962150c820f406182390e32b4b3611dfbea20b Author: Tassilo Horn <tassilo@member.fsf.org> Date: Mon Feb 11 11:41:00 2008 +0000 bugfixes-for-scrobbling-api-1.2.dpatch darcs-hash:20080211114131-c06f4-c2f2c408ec2bc02c97c9a9bcf0fe6445620973c5.gz commit a4eb8d0ae25992ac7c4250a5f2a43c1f11ee8f00 Author: Tassilo Horn <tassilo@member.fsf.org> Date: Mon Feb 11 10:26:00 2008 +0000 push-lastfm-submission-api-to-1.2.dpatch darcs-hash:20080211102659-c06f4-2588d4ae703828bfbea58d67b407bc4aaf0cded8.gz commit f8079a700d8074cd591effa969d80975794363fc Author: Michael Olson <mwolson@gnu.org> Date: Wed Jan 30 06:41:00 2008 +0000 emms-playlist-mode: Use current buffer for clear and kill. In this case of the clear and kill commands, it makes the most sense to operate on the current buffer, rather than the currently-designated EMMS playlist buffer. Additionally, fix a bug when doing "a" or "RET" on something that isn't the current EMMS track. darcs-hash:20080130064148-1bfb2-0cf2b8b59d0f338d67cd21e272bb305bd9b9ada1.gz commit 639b1fed1ceff6cbc64f2e5724f82d31b271d0ef Author: Michael Olson <mwolson@gnu.org> Date: Wed Jan 30 06:39:00 2008 +0000 emms-player-mpd (clear): Use current buffer if it is an EMMS playlist buffer. darcs-hash:20080130063956-1bfb2-dfa5407041c7f4c4ab5622636c405901bd480bc2.gz commit 87d38abc15487493da80afc3ecf92e32ed815ccd Author: Luca Capello <luca@pca.it> Date: Sun Jan 6 15:29:00 2008 +0000 emms-player-mplayer.el: allow subtitle even for URLs darcs-hash:20080106152951-f6b0c-663254836e588cd5212d30d1ce0f72e632a5d02c.gz commit eaa8db4d476216dc2f33582926eb44ece94a5923 Author: Michael Olson <mwolson@gnu.org> Date: Sun Jan 6 23:35:00 2008 +0000 emms-lastfm: Handle case where info-playing-time is unset for the current track darcs-hash:20080106233540-1bfb2-939c6c6c43ad402d4ff21bbefc10eafbafc331e0.gz commit eab6e8de15b92970e5667c1709b4a1cab1a02e5c Author: Tassilo Horn <tassilo@member.fsf.org> Date: Fri Dec 28 19:10:00 2007 +0000 delete-duplicate-def-of-emms-track-simple-description.dpatch Mathias patch added a new definition without removing the old one. darcs-hash:20071228191005-c06f4-b406d86dd1c9f1ba33285d8501d2cbe09727f5ca.gz commit 92370b0ac336b1716614e1daea48f059c372092a Author: mathias.dahl <mathias.dahl> Date: Fri Dec 28 08:59:00 2007 +0000 Format URL so that it looks nicer in playlist. darcs-hash:20071228085920-18da9-66f645e44747dcc5ca70958f5fdefc3fd79c0590.gz commit e0ca2bbebcf9d51c7450e48e9ce229744b4c60f6 Author: lucas <lucas> Date: Thu Nov 22 15:36:00 2007 +0000 emms-streams.el: add docstring for emms-stream-toggle-default-action darcs-hash:20071122153613-4f952-39660b0c51fd7e44f25538cee160176cd325f217.gz commit 56cf74cd005819114ed388d9ac2207ec1ce524ea Author: lucas <lucas> Date: Thu Nov 22 15:35:00 2007 +0000 emms-streams.el: update Philosomatika stream URL darcs-hash:20071122153554-4f952-2f89251ed6fc35181a2f6389adc1607074167cc3.gz commit 1138edb067a5ba09d3db77faf6a96f654b052b74 Author: William Xu <william.xwl@gmail.com> Date: Wed Nov 21 11:30:00 2007 +0000 New var: emms-playlist-limit-hook. darcs-hash:20071121113028-cfa61-136ae25deb325c413688a975e09622d9a05f8b65.gz commit 8146cac6e0ad1e44ea24bba7509c9d714fccfbd3 Author: William Xu <william.xwl@gmail.com> Date: Wed Nov 21 11:28:00 2007 +0000 MPlayer supports .ape files now.(at least from 1.0rc2) darcs-hash:20071121112846-cfa61-455883f0a3185b29f4bd381ed77ee50575538045.gz commit 40d7162d906ab9776d8b592e446bf1abc0763010 Author: William Xu <william.xwl@gmail.com> Date: Sun Nov 4 14:38:00 2007 +0000 When calling file-exists-p, make sure it's operated on a regular file. (This is the cause of the various tramp errors..) darcs-hash:20071104143856-cfa61-320ed4942ec58d4a5ece4f4568444a96858890a1.gz commit db6bfe9848971a857518c817acc0773d6f76738d Author: William Xu <william.xwl@gmail.com> Date: Sun Nov 4 13:27:00 2007 +0000 Only add emms-info-* to emms-info-functions when required program actually exists. darcs-hash:20071104132746-cfa61-85ca6765c3bb76e48a9753435475a4d9a9e555cd.gz commit eda10285e1fc6aeb287602d1b03590057a0d3bff Author: William Xu <william.xwl@gmail.com> Date: Mon Oct 22 09:01:00 2007 +0000 emms-lyrics.el: (emms-lyrics-find-lyric), Use `emms-source-file-directory-tree-function' instead of forceful emms-source-file-gnu-find. darcs-hash:20071022090151-cfa61-18d3188cba598803b7399e3c725fc4473ea21a46.gz commit 36806a0dd6c44f5c20b86b8a3ea9bec422750057 Author: William Xu <william.xwl@gmail.com> Date: Sun Oct 14 06:39:00 2007 +0000 Replace `nnheader-concat' with `concat + file-name-as-directory' to make XEmacs happy. darcs-hash:20071014063932-cfa61-62cac9e96ea91d9205a5932a063cff5f356ddb43.gz commit a6fe65ef66255a80dbefd60c10225abe281c1dbd Author: William Xu <william.xwl@gmail.com> Date: Fri Oct 12 02:45:00 2007 +0000 Move emms config files to a common directory: ~/.emacs.d/emms. darcs-hash:20071012024503-cfa61-0e061f1f19c1ca449aa5ac6814ba2d720f14ed9e.gz commit 9a84f872262624868c41c7dda9b907026f68304d Author: William Xu <william.xwl@gmail.com> Date: Mon Oct 8 07:09:00 2007 +0000 emms-playlist-limit.el: Fix typos and minor updates. darcs-hash:20071008070917-cfa61-fbc445a6004e8c20ed9e516ab5cbc157e21d95ed.gz commit 9a5aa42b2720a37eb7113453130e580ee4a3fbac Author: forcer <forcer> Date: Wed Oct 3 11:26:00 2007 +0000 emms-player-mplayer.el (emms-player-mplayer-subtitle-checker): Replace / with _ in track names. darcs-hash:20071003112650-2189f-597e251af82e28fe8c0c9da2c7d8e7db256eab36.gz commit 37859ca345d970415b6232707f26bdd9469e4f52 Author: lucas <lucas> Date: Tue Oct 2 12:41:00 2007 +0000 emms-browser.el: bind n and p to next- and previous-line. darcs-hash:20071002124109-4f952-305f8d18fdbb18214cec46c752c1243cf36e64b6.gz commit 88f4da96c61d691590101242c68fc09e331040ec Author: Tassilo Horn <tassilo@member.fsf.org> Date: Thu Sep 6 20:18:00 2007 +0000 fix-next-line-warning.dpatch darcs-hash:20070906201831-c06f4-9eb95ef740ca02edb572c539f1e9bc11a8a015ae.gz commit b063011f3a54d5e73d6344cbb0d78c8611ef5445 Author: Michael Olson <mwolson@gnu.org> Date: Thu Sep 6 19:22:00 2007 +0000 emms-lastfm: Allow emms-key-value to take a buffer argument. I'm trying to track down some weird "error in process sentinel: delete-process: Selecting deleted buffer" errors that occur when I poll with emms-lastfm via a timer and start gnus (which blocks until it is finished retrieving email for all inboxes). These changes don't fix the problem, but they make me feel safer nonetheless :^) . I suspect that it might be caused by a URL.el bug involving deleting the wrong buffer which was pointed out by Diane Murray last month. darcs-hash:20070906192215-1bfb2-061bd8157011c8fea52fb4fe569ad623342fe14d.gz commit 35c5e3d53e88865d17735df12c51dc7ffc59238e Author: Michael Olson <mwolson@gnu.org> Date: Thu Sep 6 19:19:00 2007 +0000 emms-browser: Fix compiler warning. Presumably the committer meant to write "performer" rather than "composer". darcs-hash:20070906191904-1bfb2-1999cf900c7123e0f790f543f9f233f60f6ef440.gz commit 9bd9bbd44f182e41428de04ee99f9ac957eda75e Author: Ye Wenbin <wenbinye@gmail.com> Date: Sun Sep 2 02:48:00 2007 +0000 format-spec expect spec character as a-zA-Z darcs-hash:20070902024848-94065-92a423e34a493d7e9e278ace8e763301bc928cee.gz commit a728137bf8409ddd144026f5f842d06c6535bc7b Author: Ye Wenbin <wenbinye@gmail.com> Date: Sun Sep 2 02:48:00 2007 +0000 Error commentation in emms-i18n darcs-hash:20070902024825-94065-e6543dff336b06851bed3bb95a4f163487bf1a4a.gz commit 4ef058ec93e87ba1bc5a541c73b691fcf6631266 Author: Ye Wenbin <wenbinye@gmail.com> Date: Sun Sep 2 02:47:00 2007 +0000 Wrong function in emms-history darcs-hash:20070902024732-94065-3d97f5b2c9342654afc5bae9836ae2a5b72ac09a.gz commit f29e12ff6fb71422a0e2fd9c59b6daf35cd2338a Author: forcer <forcer> Date: Mon Aug 27 13:31:00 2007 +0000 Simple players now use their regex property as they should. emms-player-simple.el (define-emms-simple-player): `playablep' now uses `emms-player-get' for the regex property, instead of using the hardcoded regex, as it should. Thanks to Ye Wenbin for noticing this old bug. darcs-hash:20070827133149-2189f-c1d9cec8543eec45106379d520c8d829cc31ba52.gz commit b1f1c4ad7e79f41774f5f135d93c762571c88866 Author: Tassilo Horn <tassilo@member.fsf.org> Date: Wed Aug 29 09:35:00 2007 +0000 fix-browser-covers.dpatch - If emms-browser-covers value is a function, call it with a directory as its docs say. (Before it was called with a file) - Also add to its doc-string that its second arg is a symbol (its size). - Support all image types emacs knows. darcs-hash:20070829093557-c06f4-c69286db575a025baa349ebb042ded3cd78fa5c4.gz commit 46631e0d06139949be31afdf512f0d95929830d9 Author: Michael Olson <mwolson@gnu.org> Date: Sun Aug 19 17:02:00 2007 +0000 lastfm: Allow user to specify which type of tracks get submitted darcs-hash:20070819170235-1bfb2-43caff981d10cc50fae838ea6c67fb106d0c4db1.gz commit ec320ca6d98d0ec22ce286bb8ed8ce99ee6aa0a5 Author: Michael Olson <mwolson@gnu.org> Date: Sun Aug 19 15:37:00 2007 +0000 emms-lastfm: New option emms-lastfm-submission-verbose-p This controls whether EMMS notifies the user every time a track is submitted. The default is not to do so. darcs-hash:20070819153739-1bfb2-89fecc3a7a5a66330a3608466b2d37967ad200ed.gz commit 8365f1c808490ad348c8fba82ea57f91cb1c996f Author: Michael Olson <mwolson@gnu.org> Date: Sun Aug 19 15:04:00 2007 +0000 Drop eval-when-compile around (require 'overlay) darcs-hash:20070819150408-1bfb2-c1c9ec1c084499b0e171299a91024d27a41d7db0.gz commit 03f4b18cee7f843cb8df67f2411b18d44fc941f4 Author: Michael Olson <mwolson@gnu.org> Date: Sat Aug 18 18:52:00 2007 +0000 Use slightly different XEmacs overlay fix darcs-hash:20070818185218-1bfb2-fa9c17ee4eb9fbbef332a9ecc1a0e193279c1d35.gz commit 4bcac4766f465f80cfcf08f3c3a4840e610f5882 Author: Nix <Nix> Date: Sat Aug 18 13:40:00 2007 +0000 XEmacs does not load the overlay functions by default: load them here. darcs-hash:20070818134016-984cd-9ccae7bb8cfa94f6e82bdcefb31ba927c75875ee.gz commit d4e5e5f2f58f45b79296b907ccac28272703a7fb Author: Nix <Nix> Date: Sat Aug 18 13:34:00 2007 +0000 Add support for composer and performer tags. The browser keybindings are somewhat discontiguous to avoid breaking people's finger macros: browsing by composer and performer are `b 5' and `b 6' respectively, where artist is `b 1'. In the tag editor, I changed the note format character to %;, making room for composer as %c. I've not added support to last.fm for composer or performer, as it doesn't seem to support either. (I suspect that in most cases the composer should be reported as the artist if it is present, but that is not impolemented here.) darcs-hash:20070818133412-984cd-07ed55c9bf357ee6119f6d70fc2f267e9e8ecef9.gz commit 44f24c3b68c3155099fdc484804d00ddd909170d Author: Tassilo Horn <tassilo@member.fsf.org> Date: Fri Aug 17 15:04:00 2007 +0000 docs-for-editing-tags-and-renaming.dpatch darcs-hash:20070817150402-c06f4-6e36d700851b4b80a6ac7408e630a20e35e06394.gz commit 270b8533024fae1e056a9d5dab03b21cbb8425be Author: Tassilo Horn <tassilo@member.fsf.org> Date: Fri Aug 17 10:03:00 2007 +0000 use-existing-functionality-for-renaming-files.dpatch When I implemented the renaming stuff, I was not aware that Ye already thought of this feature. When editing a track, one can edit the filename and the file will be renamed and the cache updated. Now renaming by hitting `R' (`emms-tag-editor-rename') in the playlist makes use of this functionality instead of doing it on its own. darcs-hash:20070817100310-c06f4-49ce1f24221f5701fd77be87f4823cf594bb1146.gz commit aa2ec7157503b7da1d465d6c52d6fc610d399c86 Author: Tassilo Horn <tassilo@member.fsf.org> Date: Thu Aug 16 07:01:00 2007 +0000 fix-cache-problem-when-renaming-tracks.dpatch I fixed the problem with the cache I mentioned in my last patch. darcs-hash:20070816070106-c06f4-d82d39fdf633aa7943026628a26b96fe23efbc35.gz commit e56608e2156199b226ee0f76977dc85e53cc24a5 Author: Tassilo Horn <tassilo@member.fsf.org> Date: Wed Aug 15 18:32:00 2007 +0000 support-for-renaming-files-with-tag-editor.dpatch With `R' in a playlist (calls `emms-tag-editor-rename') the file(s) corresponding to the (marked) track(s) or the track at point will be renamed according to the format specified in `emms-tag-editor-rename-format'. Work ok for me, but there's a little problem maybe someone can fix: - If users use the cache it has to be updated somehow. `emms-cache-sync' seems to remove the renamed files. So you have to re-insert all renamed tracks to get them into the cache again. darcs-hash:20070815183247-c06f4-1419a175a28e72530fba2a67ee3925a45f311a1c.gz commit eb8dcf8d1fa030351093571714cf55cc8c73fa1b Author: Tassilo Horn <tassilo@member.fsf.org> Date: Wed Aug 15 08:01:00 2007 +0000 refinements-and-docs-for-emms-history.dpatch This path makes some refinements in emms-history.el: - Start playback after `emms-history-load' only if `emms-history-start-playing' is non-nil. - Added customization group emms-history - defvar -> defcustom - better docstrings and commentary - Added Info docs. (Node "Persistent Playlists") darcs-hash:20070815080114-c06f4-fbe6c254a5dade4d6a99130fb2cc43c277ef6311.gz commit f8ba8c3683f3119e25f33d700cb900697716618b Author: lucas <lucas> Date: Thu Aug 2 21:08:00 2007 +0000 emms-score.el: change score-file to something more sane ~/.emms can be an EMMS config file, whereas ~/.emacs.d/ is already used to store the stream bookmarks file, so use it for the score file too. darcs-hash:20070802210854-4f952-ca3be4ece10fd1dcca9e912afbfa9cd9eb40da66.gz commit 62d77cbf6168261d67e037473f5ca600359dca93 Author: Tassilo Horn <tassilo@member.fsf.org> Date: Thu Aug 2 20:07:00 2007 +0000 make-S-prefix-key-for-sorting-functions.dpatch darcs-hash:20070802200758-c06f4-060512f35899d2224b3febca6b3c03a792efce84.gz commit a77d0543f55ee0c6dda07f43cee68c5d52c76981 Author: Michael Olson <mwolson@gnu.org> Date: Mon Jul 23 02:35:00 2007 +0000 Fix compiler warning in emms-setup darcs-hash:20070723023532-1bfb2-f4ef4b544e973ab66838451f249a6c62f515ad79.gz commit f6a376a5382ab46ab47db17e7b2bfdd6af792bf8 Author: Michael Olson <mwolson@gnu.org> Date: Mon Jul 23 02:34:00 2007 +0000 emms-playlist-limit: Use standard enable/disable/toggle interface darcs-hash:20070723023452-1bfb2-b892d6467fb456079587713fa4d188b4d061f3d1.gz commit bda55f5f49480c19c080a66a51c4686d2ab5cfbf Author: Michael Olson <mwolson@gnu.org> Date: Mon Jul 23 02:03:00 2007 +0000 emms-streams: New option emms-stream-repeat-p Instead of assuming that everyone will want to automatically repeat a streamlist if it runs out of tracks, make this controlled by the `emms-stream-repeat-p' option, which defaults to nil. darcs-hash:20070723020304-1bfb2-7ec05852decba27348abbef01daefbe8db026bbc.gz commit 0c4c096ff27aa9dcd54a7510e7eae97585088639 Author: Michael Olson <mwolson@gnu.org> Date: Mon Jul 23 01:59:00 2007 +0000 emms-player-mpd: Fix bug with selecting an individual URL track to play from a streamlist darcs-hash:20070723015956-1bfb2-e9fdefb2e8a6897384a6d8f1ca8ccb5016415631.gz commit 48f7fad6239b112fd77a275102c8c0f9babc867f Author: Michael Olson <mwolson@gnu.org> Date: Mon Jul 23 01:57:00 2007 +0000 emms-player-mpd: Make callback arg for emms-player-mpd-sync-from-emms optional darcs-hash:20070723015722-1bfb2-917e1a705e793f4b1f9c34a0d0168aaa38efb355.gz commit 264008fdcd1c65ba83b60d15badd71d8182d983e Author: William Xu <william.xwl@gmail.com> Date: Thu Jul 19 06:50:00 2007 +0000 emms-playlist-sort.el: Bind "s s" to emms-playlist-sort-by-score. darcs-hash:20070719065003-cfa61-562ce88764bc18f0043394984f286c6f5bbc15fb.gz commit 4aafb3e717f98ca48467826e0bad146dfd8c4c90 Author: William Xu <william.xwl@gmail.com> Date: Tue Jul 17 13:15:00 2007 +0000 emms-setup.el: Enable emms-score in emms-devel. darcs-hash:20070717131538-cfa61-9a56afce87ac9b7f8619b1de9e0532ea07bef5c4.gz commit a268ebf390ab047a008f3d23316108036ee5a285 Author: William Xu <william.xwl@gmail.com> Date: Tue Jul 17 10:09:00 2007 +0000 emms-lyrics.el: Set default value for emms-lyrics-dir to ~/music/lyrics. darcs-hash:20070717100946-cfa61-180581868458fce85e1affc4ecf564a7e9e7bf6b.gz commit 3b34bdd7fb862f8784ce55990919ac5cb3b61803 Author: William Xu <william.xwl@gmail.com> Date: Tue Jul 17 09:54:00 2007 +0000 emms-playlist-sort.el: Remove emms-playlist-sort-prefix to make the codes more clean. And steal "s" prefix key from `emms-playlist-mode'. (An alternative for emms-playlist-mode could be "v", same as XMMS) darcs-hash:20070717095454-cfa61-175bb84a0173d810d35cf994a06f37cf22eded81.gz commit a17384af097c2c62d1a434cbee00ccbac72fd33a Author: William Xu <william.xwl@gmail.com> Date: Tue Jul 17 08:25:00 2007 +0000 emms-playlist-limit.el: (define-emms-playlist-limit) Fix prompt string bug. darcs-hash:20070717082536-cfa61-55775fe2860eff7122ef60b493ad62d614e113bb.gz commit 11bc711f9727efbe6bddc6512b396de0314bd483 Author: Tassilo Horn <tassilo@member.fsf.org> Date: Thu Jul 12 06:20:00 2007 +0000 make-number-of-secs-to-seek-configurable.dpatch Patch sent by "Alfred M. Szmidt" <ams@gnu.org> in <20070711183504.EFD58301E5@Psilocybe.Update.UU.SE> on the emms-users list (with slight modifications). darcs-hash:20070712062052-c06f4-032102b01507ffc27f211c29cb5375ab862f22dc.gz commit cc9aff2561eb18b720539cb43d2d43e06d54a75c Author: Michael Olson <mwolson@gnu.org> Date: Thu Jul 12 21:14:00 2007 +0000 Avoid even the most remote possibility of a conflict with color-theme.el and its very bad replace-in-string function darcs-hash:20070712211444-1bfb2-74a2030fdfba44cfe7e2acb687783bdab1e23822.gz commit cb8dad409fd2116e51f73c94e48e62ef493234f7 Author: William Xu <william.xwl@gmail.com> Date: Wed Jul 11 07:10:00 2007 +0000 emms-playlist-limit.el: Add missing line: (define-emms-playlist-limit info-title). darcs-hash:20070711071022-cfa61-6af7cce5b0b4c5b0a92a93c2452be16da1090beb.gz commit b9d1759434443695370b7b2424e12b9ee03e6a1d Author: William Xu <william.xwl@gmail.com> Date: Mon Jul 9 10:37:00 2007 +0000 emms-playlist-limit.el: Minor updates. darcs-hash:20070709103714-cfa61-907861f878bb0b0e100bd0070d81b4c12a2bd7ba.gz commit f3690237e3602d2594ac49b5f5227ad18319049d Author: William Xu <william.xwl@gmail.com> Date: Sun Jul 8 14:00:00 2007 +0000 emms-playlist-limit.el: Update Copyright to GPLv3. darcs-hash:20070708140012-cfa61-f9ee9504af967f99aba76d3ae6910ee37f55231d.gz commit c08b637e52279de40e365a55d5361b03461aadf9 Author: William Xu <william.xwl@gmail.com> Date: Sun Jul 8 12:00:00 2007 +0000 emms-playlist-sort.el: Minor updates. darcs-hash:20070708120050-cfa61-c1714b94ed7b1e12993fc6b7fc526bbf92b33653.gz commit 2a545525c7b0286b828f9a1b98cf38dfeeeec6b6 Author: William Xu <william.xwl@gmail.com> Date: Sun Jul 8 11:59:00 2007 +0000 emms-playlist-limit.el: Redefine functions emms-playlist-limit-to-* with macro: define-emms-playlist-limit. darcs-hash:20070708115907-cfa61-f70eb7df3c4e775cae1430dc2b57d3471b4b5d2e.gz commit 35c8ce2f4e0e1a98b9422a96e9579469f641f099 Author: William Xu <william.xwl@gmail.com> Date: Sun Jul 8 04:08:00 2007 +0000 emms-playlist-limit.el: Add default value based on track at point for emms-playlist-limit-to-*. darcs-hash:20070708040809-cfa61-9b5b97d1099915a83c9f8eea8949ac4c1747d3c0.gz commit 3b6c9a35fafca4eaa9ad5896ffae782ed2348e10 Author: William Xu <william.xwl@gmail.com> Date: Thu Jul 5 16:02:00 2007 +0000 New file: emms-playlist-limit.el. And minor updates to emms-playlist-sort. darcs-hash:20070705160221-cfa61-c16a2727863237aa851657d35705cd8cbfed3145.gz commit 2662277d79bd1ac1f4b376f0f1486c8731017931 Author: William Xu <william.xwl@gmail.com> Date: Sat Jun 30 12:47:00 2007 +0000 emms-player-mplayer.el: Add "eng.srt", "chs.srt", "cht.srt" to emms-player-mplayer-subtitle-extensions. darcs-hash:20070630124728-cfa61-2533e002f5703780be546569560fd227be453d62.gz commit 374d2f4d2b8505244dc9ae51b13f5caac138aed3 Author: forcer <forcer> Date: Fri Jun 29 16:39:00 2007 +0000 Updated NEWS for post-3.0 darcs-hash:20070629163917-2189f-075489b335086448e5512b91de0d96f493185dff.gz commit 2d73ddcfabeff142a6448d58cbebbce15beda2ba Author: forcer <forcer> Date: Fri Jun 29 16:17:00 2007 +0000 Remove debian procedures from the RELEASE file darcs-hash:20070629161733-2189f-3c7e23fe7e80d1e2c0fbd327f8b5758164d65972.gz commit 049e877c3bd23c0ab184c5cbe029b7ebd9f09d58 Author: forcer <forcer> Date: Fri Jun 29 16:10:00 2007 +0000 Remove debian directory, it's maintained elsewhere now darcs-hash:20070629161023-2189f-8e01f6cbc23c40df3e4bf3c79182728fae659f86.gz commit 9463aa0abef27e2d9fda07669a165410e713d0d7 Author: forcer <forcer> Date: Fri Jun 29 16:09:00 2007 +0000 COPYING and gpl.texi updated for GPLv3 darcs-hash:20070629160924-2189f-8ac0bbdc3a8cba1f642df7139046357d37730984.gz commit 4f9b15d12a3aece004901414ee791f23f8051ea5 Author: William Xu <william.xwl@gmail.com> Date: Tue Jun 26 07:16:00 2007 +0000 NEWS: Now emms-player-mplayer is capable of loading movie subtitles. darcs-hash:20070626071626-cfa61-fea102574dc27a0fc33fa45fe2f31b2427050877.gz commit 2a3b9b27b7578dc4d9ef93dbd7176b8ae15462c2 Author: Michael Olson <mwolson@gnu.org> Date: Fri Jun 29 02:21:00 2007 +0000 Mention location of mailing list and website darcs-hash:20070629022117-1bfb2-7533c8a0c661d28ddf7894cb77521929e5be32db.gz commit 1c5692efd0fe85c6391de11dc445116d364fdb6f Author: Tassilo Horn <tassilo@member.fsf.org> Date: Tue Jun 26 19:13:00 2007 +0000 simplify-lastfm-timer-cancelation-and-bump-version.dpatch darcs-hash:20070626191355-c06f4-ae6c018d47f4cd90c8fe1e76b6ad533d9c5b5a08.gz commit 8117a9b46545993a1306c6381aa5efcf0191498a Author: Tassilo Horn <tassilo@member.fsf.org> Date: Tue Jun 26 14:12:00 2007 +0000 change-all-file-headers-to-gpl3-or-later.dpatch darcs-hash:20070626141221-c06f4-e034ff32ecc6e2d57ffaefaeb4f78d1e36a830a2.gz commit 4fe5f9e155b5374fc6f0de03225c51942d134854 Author: Tassilo Horn <tassilo@member.fsf.org> Date: Tue Jun 26 11:41:00 2007 +0000 change-copyright-of-manual-to-fsf.dpatch darcs-hash:20070626114123-c06f4-034acc1bd2c5d2465afe6eddcd9a1c5317679bc5.gz commit c1ee15b5a9a2a6468fef2a648e29492ff7dd2cf5 Author: Tassilo Horn <tassilo@member.fsf.org> Date: Tue Jun 26 11:23:00 2007 +0000 some-manual-fixes-and-addition.dpatch Fixed some markup in the tag editor section and made some clearifications in the last.fm section. darcs-hash:20070626112320-c06f4-904ebfe398ea06e093889e34d16874ddbfe59209.gz commit c2d32494d55894c70935514bd55378bcc14fb365 Author: Ye Wenbin <wenbinye@gmail.com> Date: Tue Jun 26 02:32:00 2007 +0000 update headers of emms-history.el and so on. darcs-hash:20070626023252-94065-b4d98c8dd111981ba80a479ced3440bb0ee2d58d.gz commit cd9499058def01b9300acc89ada53ec961204be9 Author: lucas <lucas> Date: Mon Jun 25 08:07:00 2007 +0000 emms-last-played.el: update headers, (C) is now to FSF darcs-hash:20070625080705-4f952-e4307f0adb3d66e019a90c744a3504b8fdac0d1c.gz commit 9f620c29aabd6475536bdb18d84ab2ff55e884eb Author: William Xu <william.xwl@gmail.com> Date: Mon Jun 25 04:19:00 2007 +0000 emms-player-mplayer.el: Turn on emms-player-mplayer-start-with-subtitle-checker by default. I think it is very helpful for playing movies. darcs-hash:20070625041949-cfa61-07a8ec7e25d664304d7e2ad44908ac0f2813dade.gz commit 33d0e31b3de4d20e8058c7cc0019ef7ddd9caa2f Author: William Xu <william.xwl@gmail.com> Date: Sun Jun 24 07:11:00 2007 +0000 emms-player-mplayer.el: Load in all found subtitles instead of forcing user to choose one. darcs-hash:20070624071131-cfa61-936bb6479d5502f83dc0e3e1094259d681d96f60.gz commit ac30913c6fade5126bb8c7bac92d85f6eaf58e58 Author: William Xu <william.xwl@gmail.com> Date: Thu Jun 21 15:57:00 2007 +0000 emms-player-mplayer.el: Use `emms-replace-regexp-in-string' instead of `replace-regexp-in-string'. darcs-hash:20070621155753-cfa61-d0fc271fe119c547e17eab16fe393d541a6d45ec.gz commit a55fa5da02057f1955ce8abfac7fc173fa5bd659 Author: William Xu <william.xwl@gmail.com> Date: Thu Jun 21 15:55:00 2007 +0000 emms-player-mplayer.el: New variable: emms-player-mplayer-subtitle-extensions. darcs-hash:20070621155548-cfa61-fa61b2eca9ad5eb4085e5401db809f023304f5cb.gz commit 0f92c8f2851542b482047bf138ac14fa735fc228 Author: Ye Wenbin <wenbinye@gmail.com> Date: Thu Jun 14 15:58:00 2007 +0000 Rename track file after confirm by user darcs-hash:20070614155834-94065-5daec0b01f392ead46ee58d88544703da34e3057.gz commit a01b8a208cf8820d8c777a48c3af08e21688a30e Author: Ye Wenbin <wenbinye@gmail.com> Date: Thu Jun 14 15:58:00 2007 +0000 Write ogg tag use upcase fields darcs-hash:20070614155806-94065-683464c11c64d331b912ceb712f571778f2ffc3a.gz commit e1a62e1ec9abb61e3758616d48288f493d06f9d2 Author: Ye Wenbin <wenbinye@gmail.com> Date: Sat Jun 9 02:55:00 2007 +0000 Fix a typo darcs-hash:20070609025545-94065-069438ac164738b51bca7bd92acc77a9870be09d.gz commit 01d1a873398ec7ceb1779be45590b200237eaf46 Author: Tassilo Horn <tassilo@member.fsf.org> Date: Mon Jun 11 06:28:00 2007 +0000 remove-xine-from-default-players-list.dpatch See Message-ID: <m31wgmuv97.fsf@fleche.redhat.com> on the mailing list. darcs-hash:20070611062849-c06f4-59ebaaf0a1135478ba5fa7c958a9fd4a29b06ee2.gz commit 55447381b73bf6a2165e083acc0a52a45608ac5a Author: Michael Olson <mwolson@gnu.org> Date: Sun Jun 10 16:49:00 2007 +0000 emms-tag-editor: Fix compiler warning darcs-hash:20070610164902-1bfb2-6c0568753cfff5deb6ebe8d750868749b7950611.gz commit a5183d7a30406d6d2f868c75ba73fff6af33798c Author: Michael Olson <mwolson@gnu.org> Date: Sun Jun 10 16:47:00 2007 +0000 emms-mark: Set emms-playlist-buffer-p darcs-hash:20070610164738-1bfb2-7e73dd314d905e98150dcd79e67cef7a8106306d.gz commit afe73952504eb92770fc59d27936396ebb28b4a5 Author: Ye Wenbin <wenbinye@gmail.com> Date: Sat Jun 9 02:37:00 2007 +0000 Add command emms-tag-editor-guess-tag-filename I'm not familiar to regexp internal, so the emms-tag-editor-compile-pattern may not robust or have bugs. Any advice will be wellcome. darcs-hash:20070609023733-94065-1060f4dc3fedbf75afd94c22cd7412d0dffe1c61.gz commit 61f2cfe63ca9dad64ef214b9db03d70a9c10eed8 Author: Ye Wenbin <wenbinye@gmail.com> Date: Sat Jun 9 02:34:00 2007 +0000 Fix bug in transpose tag darcs-hash:20070609023409-94065-e999c77f14a22e48125608e9b6d0ca8158b6f555.gz commit b4584727981af9d3fa38947bd44c84ab21bf9470 Author: lucas <lucas> Date: Wed Jun 6 09:06:00 2007 +0000 emms-streams.el: update DNA Lounge Live address, add DNA Lounge Radio darcs-hash:20070606090620-4f952-6371dcdc2c988f57cb46d3a2c47bd2b09fa91270.gz commit 0ae81d5b4342741bfcd87a1056d6ae0cbcd386d1 Author: Michael Olson <mwolson@gnu.org> Date: Wed Jun 6 02:06:00 2007 +0000 emms-mark, emms-tag-editor: Improve documentation and messages darcs-hash:20070606020643-1bfb2-fe16b89855d731eb81f486db0c82d3d8d5f46cbc.gz commit de212a1c6205eb45ff712eb0f5ef0d91abcd6be3 Author: Martin Schoenmakers <aiviru@diamond-age.net> Date: Tue Jun 5 13:23:00 2007 +0000 volume-autoloads This patch adds autoload comments to the emms-volume 'UI' functions, as well as to the 'backend' function in emms-volume-amixer file. This seems like the right thing to do, offhand, not really knowing much about autoload stuff ;) darcs-hash:20070605132340-97144-da0ae5713037e784e7570cfe5437fb765db1686d.gz commit 5d5475c6069037fb678fa68b33afa0d0c72901eb Author: William Xu <william.xwl@gmail.com> Date: Tue Jun 5 08:57:00 2007 +0000 emms-playlist-mode.el: (emms) `emms-add-file' actually understands both file and directories, so let's use `emms-add-file'. darcs-hash:20070605085746-cfa61-80bf6246e667746da96834c9d1559284b8d5a5b4.gz commit f57e6f4b0eb4f730107c4a912bd20b1de756f746 Author: Tassilo Horn <tassilo@member.fsf.org> Date: Tue Jun 5 07:54:00 2007 +0000 add-function-emms.dpatch The new function `emms' calls `emms-playlist-mode-go' and queries for a directory of music files to add to the playlist, if it is empty. darcs-hash:20070605075453-c06f4-d57382a594c2191e118eb88f5017a2e897f6fad3.gz commit a192a89d5536dfcd8ec4d08004b3b19e1d7d885b Author: Michael Olson <mwolson@gnu.org> Date: Wed May 30 01:02:00 2007 +0000 tq.el: Add year to copyright header to match Emacs 22 darcs-hash:20070530010248-1bfb2-18149bb0b824a8ee69784b4497ca4484f3f3ed63.gz commit c1179b00dd8310c7f0575fa576ea8c1158916bde Author: Michael Olson <mwolson@gnu.org> Date: Sat May 26 21:16:00 2007 +0000 tq.el: Fix edge case darcs-hash:20070526211610-1bfb2-fd67edfe8ce03e72bef3d330b396d0fc516f115c.gz commit fcc4cfffacdab4e3eef129e3a1e4a28b60c1c4ea Author: Ye Wenbin <wenbinye@gmail.com> Date: Mon May 21 07:01:00 2007 +0000 Deactivate mark when mark activate darcs-hash:20070521070130-94065-b642910b76fcc3aa1c344b1f543fe1f91edb43ed.gz commit 8b3c65357e684ae794b5c488c927a093e6d6967a Author: Ye Wenbin <wenbinye@gmail.com> Date: Mon May 21 07:00:00 2007 +0000 add document for some commands darcs-hash:20070521070049-94065-36a4faaa4118198646a8131ee8ffd5776fd7eadd.gz commit a9b3bfea81e3edc625152051d32417ef3e194b11 Author: Ye Wenbin <wenbinye@gmail.com> Date: Mon May 21 06:51:00 2007 +0000 Highlight text to replace, add doc for the command darcs-hash:20070521065107-94065-b55aac1aaed355a50b8643ef1d77732c170cd6fe.gz commit 806cbec32117e9ef1434cad34c91ec894ab07fb4 Author: Ye Wenbin <wenbinye@gmail.com> Date: Mon May 21 06:28:00 2007 +0000 Set tag even if the tag is empty darcs-hash:20070521062827-94065-df982456724837444c4491e57aa5086d6ca37b32.gz commit 8fa660f88b6380f22815fde571f5ad489e900b07 Author: Michael Olson <mwolson@gnu.org> Date: Wed May 16 23:58:00 2007 +0000 emms-streams: Stream maintenance Remove gotwoot.net, since it has been down for a month. Add several community stations (including KRUU which is powered by Free Software). Relabel Mostly Classical as a SKY.fm station, and add their Jazz station. darcs-hash:20070516235859-1bfb2-459c596da09d25b983d4747c4a923bf63dddbc95.gz commit a1e0284395d623706d797bc8110e59298865c999 Author: Michael Olson <mwolson@gnu.org> Date: Tue May 15 12:45:00 2007 +0000 emms-player-mplayer: Use emms-remove-if-not emms-remove-if-not is to be used instead of remove-if-not, because the latter is only available in the CL library, and we're not supposed to depend on that if our code gets included in Emacs. darcs-hash:20070515124505-1bfb2-b4517be2f6d6454c584791c350bbec7d67d9ff81.gz commit 3fff71cac113718bc0186a4d20a7b2592b6bc63d Author: William Xu <william.xwl@gmail.com> Date: Tue May 15 05:57:00 2007 +0000 emms-player-mplayer.el: Minor lexical change, "subscript" -> "subtitle". darcs-hash:20070515055745-cfa61-df5657aabe6845eeb581713253c418ed126dabfa.gz commit fdf11ef9e071f2743f7417d3da91cb4cf33d39d3 Author: William Xu <william.xwl@gmail.com> Date: Tue May 15 05:35:00 2007 +0000 emms-player-mplayer.el: (emms-player-mplayer-start-with-subscript-checker): New function. Now mplayer could prompt you to select subscripts when possible. To use, just make it override `emms-player-mplayer-start'. darcs-hash:20070515053552-cfa61-8cc4323446da6396b77eae6f3a5bbbecdd23e143.gz commit 0294df91c5a8a7129fe4e4b76fe4a9aafc0caf22 Author: William Xu <william.xwl@gmail.com> Date: Mon May 14 08:57:00 2007 +0000 emms-lyrics.el: (emms-lyrics-display): Fix "displaying only on minibuf" bug, it works now. darcs-hash:20070514085722-cfa61-dfd13b132c204b51493467a096aa57e085647184.gz commit 28e694dbe9cef653d4cf50deecb32dd67d474c89 Author: Damien Elmes <emms@repose.cx> Date: Fri May 11 21:35:00 2007 +0000 add .m4a support to mplayer plugin darcs-hash:20070511213548-4e3e3-e42d9cb5d377280372f6c4b183a4f0d4d85da2ac.gz commit f57d5122531628ee68ad2a9b8b0c057ebf54ef93 Author: William Xu <william.xwl@gmail.com> Date: Thu Apr 26 07:13:00 2007 +0000 emms-tag-editor.el: Valid emms-track line should start from beginning of the line, so that we can copy & paste stuffs tainted with 'emms-track property as well. darcs-hash:20070426071317-cfa61-f7ce531e7952eff61318b65df063430c2bd5f174.gz commit 864801b7f281534cd7765c214ac5634f40c42059 Author: Michael Olson <mwolson@gnu.org> Date: Wed Apr 25 01:58:00 2007 +0000 emms-streams: Update Digitally Imported URLs darcs-hash:20070425015813-1bfb2-467b161e1f6f233fa48c06640f7decf15ff414f2.gz commit 3c14966d658a902168b14d5c2e9c79974c5b051c Author: Michael Olson <mwolson@gnu.org> Date: Mon Apr 9 05:55:00 2007 +0000 emms-lastfm: Take care of url buffers sooner I removed emms-lastfm-buffer and just had all of the sentinel-type functions delete their buffer as soon as they are done with it. I was worried about functions stepping on one another's buffers, especially when one of them is in a timer. Take advantage of the fact that url sentinel functions are guaranteed to have current buffer be the one we want. Also, pass a buffer argument to emms-http-decode-buffer to satisfy my paranoia about buffer change. darcs-hash:20070409055513-1bfb2-d16a81f2fa500d9b223770d232690b217a3431f8.gz commit de2edaf1dce1e13b0212845b290178d97997067c Author: Michael Olson <mwolson@gnu.org> Date: Mon Apr 9 05:54:00 2007 +0000 emms-url: Avoid stringp errors when fetch of page failed darcs-hash:20070409055428-1bfb2-caef9a48dbe90295d8dc374de00143e77cf19803.gz commit 5495e8c0655a1e5137ceaf0cc8331433cdae54bf Author: Michael Olson <mwolson@gnu.org> Date: Mon Apr 9 05:19:00 2007 +0000 emms-player-mpd: Fix erroneous extra message and be more careful about the current buffer darcs-hash:20070409051913-1bfb2-c965d42ac45f6510003919c6cba7783164028ea3.gz commit 8652257258a7306505f24360b54284cca6308d3c Author: Michael Olson <mwolson@gnu.org> Date: Mon Apr 9 01:43:00 2007 +0000 emms-lastfm: Don't show status messages when getting metadata darcs-hash:20070409014302-1bfb2-2a784b75760d612ace6af8c25284c1787479e0c1.gz commit 715b5a5c569640cc5a293bc3bada078d562b43f2 Author: Michael Olson <mwolson@gnu.org> Date: Sun Apr 8 23:38:00 2007 +0000 Fix use of `message', silence mpd-show if callback given and no song playing darcs-hash:20070408233853-1bfb2-c36da9a1961e7186ea3afd81445a011500cd7d64.gz commit 7c05231415f877a3902f4f247b512c5373a08407 Author: Michael Olson <mwolson@gnu.org> Date: Sun Apr 8 20:50:00 2007 +0000 emms-player-mpd: Integrate with emms-lastfm to show track * emms-lastfm (emms-lastfm-np): Expand to take optional callback argument. Rename `arg' to `insertp' for clarity. * emms-player-mpd (emms-player-mpd-show-1): Detect if emms-lastfm is activated, and if the current track is a LastFM URL. If so, call emms-lastfm-np rather than continuing on. (emms-player-mpd-show): Docfix. darcs-hash:20070408205000-1bfb2-6207ca703571a4602c7b1510f62be33df9722a8d.gz commit 2bb38ee60a4f6de5ca6ac74a007bd27ec59f8c07 Author: Ye Wenbin <wenbinye@gmail.com> Date: Sun Apr 8 11:35:00 2007 +0000 fix mp3info arguments order darcs-hash:20070408113504-94065-85ec95b40f5655477105d1e2e73bcf46f198f7e5.gz commit 21804acc049e7b0c826dbe6394f9df781a7f11e6 Author: Ye Wenbin <wenbinye@gmail.com> Date: Sun Apr 8 11:31:00 2007 +0000 Fix no changes found when val is change to empty darcs-hash:20070408113129-94065-4abe8743412c621c46f6d6e1136222e4c86d2754.gz commit 9349465d281f49f3df7bf0255d82f04298a082c7 Author: Ye Wenbin <wenbinye@gmail.com> Date: Sun Apr 8 11:13:00 2007 +0000 Fix order of emms-cache-set-function arguments. darcs-hash:20070408111309-94065-0a835a494fdb296418a704a27aa8153cc419f055.gz commit c3037cc5b844ed16abf2b1f848780eed2da51fd5 Author: William Xu <william.xwl@gmail.com> Date: Tue Mar 20 12:00:00 2007 +0000 emms-source-playlist.el: emms-source-playlist-parse-m3u, emms-source-playlist-parse-pls recognize `mms://' as urls now. darcs-hash:20070320120017-cfa61-ecd17660c8ecdf95fd6bd6490a3f214a448cde92.gz commit d0a2dfeade16ee3d01c8e56057b7ad84c7554c6d Author: William Xu <william.xwl@gmail.com> Date: Tue Mar 20 11:58:00 2007 +0000 NEWS: emms-lyrics now support lyrics auto-scrolling. darcs-hash:20070320115825-cfa61-3fedb985bbd7f344e8fdaaa00962d35e1aeb5ff3.gz commit e364b1999d4dde5a54e212792b987600ee7c5813 Author: William Xu <william.xwl@gmail.com> Date: Tue Mar 20 11:57:00 2007 +0000 emms-mode-line.el: Make `emms-mode-line-toggle' just work.. darcs-hash:20070320115727-cfa61-0ee8c7a2aa79be18ebfae19b7a6596e9fb84ae11.gz commit 328701f03d5128ba40ade0565025ba07d319ffab Author: Michael Olson <mwolson@gnu.org> Date: Tue Mar 20 11:49:00 2007 +0000 emms-streams: Fix nectarine URL darcs-hash:20070320114903-1bfb2-85f2037d2181634f0fa207f09f4cd796386cee6f.gz commit 21393cf4dc00136aa92235a5222c822a08f5bc74 Author: Michael Olson <mwolson@gnu.org> Date: Mon Mar 19 14:58:00 2007 +0000 Bump copyright years to 2007 and standardize statement Files made by those who haven't yet completed the assignment process remain copyrighted by that person. Those who have assigned have their files changed to be copyrighted by the FSF, but retain their Author line for the sake of giving proper credit. darcs-hash:20070319145852-1bfb2-2a4bb04c74262f43732fa5a81aa2d488da502995.gz commit 0914db5c7b094b7233f97d561d6cead61e400159 Author: William Xu <william.xwl@gmail.com> Date: Mon Mar 19 05:13:00 2007 +0000 emms-playing-time.el: Minor docstring updates. darcs-hash:20070319051306-cfa61-99781b572ba5eef00e1e72d2194691818b98a546.gz commit 4a52382b9084675a140285e32e0ca011d5b8ed19 Author: William Xu <william.xwl@gmail.com> Date: Sun Mar 18 10:54:00 2007 +0000 emms-volume-amixer.el: Add more docs for variable `emms-volume-amixer-control'. darcs-hash:20070318105444-cfa61-060471a97680036c7e4440cad4b9e9ee2e7c19a2.gz commit fcee10df467011a1d767c1c5ccc0321702f67ce6 Author: William Xu <william.xwl@gmail.com> Date: Sun Mar 18 10:44:00 2007 +0000 emms-setup.el: Add `emms-volume' to `emms-devel'. darcs-hash:20070318104435-cfa61-70e2432f889b4d0e2eacae2d9d1be5bf84fa2e18.gz commit b4bc1faba6489d2863b6c105eb1f394124ea3963 Author: William Xu <william.xwl@gmail.com> Date: Sat Mar 17 09:23:00 2007 +0000 emms-playlist-sort.el: Make `emms-string<' silent when some argument is nil. darcs-hash:20070317092305-cfa61-5939905142385889ddfd77f12fc23ac3c6b49d07.gz commit dfd7b747366c5cd18d62766151f938100e08e1b2 Author: William Xu <william.xwl@gmail.com> Date: Thu Mar 8 11:55:00 2007 +0000 emms-playlist-sort.el: Add `emms-string<', making string sort case insensitive. (This makes more sense in cases like sorting according to artist, etc) darcs-hash:20070308115507-cfa61-7caf3b20e7c4c1ba53ba732fbb799e68da52c8c4.gz commit 454ab8e97c30508f958b9417d81005bc79c638cd Author: Michael Olson <mwolson@gnu.org> Date: Sun Mar 18 06:48:00 2007 +0000 emms-streams: Add a bunch of radio stations darcs-hash:20070318064813-1bfb2-a04b63dd4744bf1ff9255f685c97599330c8d5bc.gz commit 879c72352c0e2660dacabed5648fb8433bbf02bd Author: Michael Olson <mwolson@gnu.org> Date: Sat Mar 17 07:04:00 2007 +0000 Fix conflicts in emms-tag-editor patch darcs-hash:20070317070451-1bfb2-e70494207b236439512e416d75d57d80255410d8.gz commit 1555e86d66131da72a6b1cf94706d662a2f49425 Author: Ye Wenbin <wenbinye@gmail.com> Date: Fri Mar 16 07:50:00 2007 +0000 Don't display message when encounter error darcs-hash:20070316075057-94065-61127edd46eb789b5060d10072376c06faf2af3b.gz commit 71aa2809de959a24ab66a40f7892ab7a7224c28c Author: Ye Wenbin <wenbinye@gmail.com> Date: Fri Mar 16 07:50:00 2007 +0000 put filename as last argument in emms-tag-editor-tag-file darcs-hash:20070316075015-94065-8e5cb73a6899d2eccb68f17d22f3d0fdef753255.gz commit e128c95a92637bd7919cd9d02587f5279b3ee0ee Author: Tassilo Horn <tassilo@member.fsf.org> Date: Fri Mar 16 14:47:00 2007 +0000 fix-mp3-tagging-args-order.dpatch darcs-hash:20070316144749-c06f4-53f17af7130aae6d35efeb715e126a2de44bbe15.gz commit bb821ef781bf07fb1de367a0ec8b4f1940906d5c Author: Ye Wenbin <wenbinye@gmail.com> Date: Thu Mar 8 14:14:00 2007 +0000 Add doc for emms-tag-editor darcs-hash:20070308141415-94065-3d08068b5eeab98f5a95a92a3634a9abf7d30f71.gz commit 1d79d0701c1b682534d17abbd20d3057fbe70d64 Author: Ye Wenbin <wenbinye@gmail.com> Date: Thu Mar 8 14:13:00 2007 +0000 Change document about emms-mark-regexp, and add more darcs-hash:20070308141340-94065-2368578753b8b9c1f500d22f5548c8f610cdd53b.gz commit 3d055f170e72b36b0de7fc1e86bcc9f3a02f1622 Author: Ye Wenbin <wenbinye@gmail.com> Date: Thu Mar 8 14:12:00 2007 +0000 Add two extra command in tag editor. Rename emms-tag-editor-replace-all darcs-hash:20070308141238-94065-8d8dba74575bede5f583ee75908f3532615b8a2d.gz commit b2f7c64fac09ee7765043ade6a063859cd8406eb Author: Ye Wenbin <wenbinye@gmail.com> Date: Thu Mar 8 14:12:00 2007 +0000 Record programs error in log buffer darcs-hash:20070308141209-94065-e42c62f7816a62ada269de9ed57d14fa05289a6f.gz commit 03e4d2db0c506895a2d3b1a8a651e3536fddb86e Author: Ye Wenbin <wenbinye@gmail.com> Date: Thu Mar 8 14:11:00 2007 +0000 Make name readonly in emms-tag editor buffer darcs-hash:20070308141123-94065-8a889520d49cf3d7bd8638d82f38e40dadc0247e.gz commit cb4e6dafa616cbe1c629392f0348d3098bf8c764 Author: Ye Wenbin <wenbinye@gmail.com> Date: Thu Mar 8 14:11:00 2007 +0000 Fix a typo error darcs-hash:20070308141101-94065-603b79b4f9dd6d197349f56d1282c673cff0f4b7.gz commit a3a1a313469a1e4bf007fea48d866a4e985d7a45 Author: Ye Wenbin <wenbinye@gmail.com> Date: Thu Mar 8 14:08:00 2007 +0000 Obsolete emms-mark-unmark-regexp, use C-u M-x emms-mark-regexp instead darcs-hash:20070308140837-94065-b6fdfb90c27a3f79de5f074d7c0d3096751e96f8.gz commit 2901997cb0343b6fd970402b8de5e52eadc712ff Author: Ye Wenbin <wenbinye@gmail.com> Date: Wed Mar 7 03:04:00 2007 +0000 Avoid print wrong history value. darcs-hash:20070307030452-94065-0c29da4ca2ab3e5e8ced49d9f88d6882bb16c893.gz commit 15807814c2d6d8ca1cfb9f386480dbdab11a8f73 Author: Michael Olson <mwolson@gnu.org> Date: Tue Mar 6 02:36:00 2007 +0000 Resolve conflict in change to manual darcs-hash:20070306023616-1bfb2-b06a97541a28ee7e84793b4de5a78b872b3f0756.gz commit 3b20b7fd3462d5d9d712ee4f199cd0b23e05faaa Author: William Xu <william.xwl@gmail.com> Date: Mon Mar 5 06:58:00 2007 +0000 emms-lyrics.el: Update comments about "Known problems". darcs-hash:20070305065844-cfa61-0a478ff6e4a31166d7477428359ab3abe3054a4a.gz commit 9807d62d0598eb6666b964fcd22f7e48d806d983 Author: William Xu <william.xwl@gmail.com> Date: Mon Mar 5 06:46:00 2007 +0000 emms.texinfo: Add possible solutions for asynchronical issue for lyrics. darcs-hash:20070305064615-cfa61-a04092118c3d3dfcf0544f5cd7011a80340a8653.gz commit fa5fb58e464fc2e75a57bd1c298b4441a9e3ccdc Author: Damien Elmes <emms@repose.cx> Date: Mon Mar 5 13:14:00 2007 +0000 browser: display a help message on an empty deck darcs-hash:20070305131445-4e3e3-e06fe61d90892014f787578c7adeaec9e45b8736.gz commit abf3484a89744526317f6e6e7fc9523580ed96d2 Author: William Xu <william.xwl@gmail.com> Date: Mon Mar 5 05:44:00 2007 +0000 emms-setup.el: Add emms-tag-editor module to `emms-devel'. darcs-hash:20070305054414-cfa61-a5c5ca69aa0e732f705b2fdc4373f83dbb595bb6.gz commit 2dcaf88e6262c701ab7a8f175a369de0a64b9876 Author: William Xu <william.xwl@gmail.com> Date: Mon Mar 5 05:39:00 2007 +0000 emms-lyrics.el: Find chinese lyrics based on filename instead of `title' from the tag info. (thus to avoid dealing with different tag info coding systems.) darcs-hash:20070305053910-cfa61-50ac2c72c140ef4e64fa2a85c4b2f8e9a3478238.gz commit 12bb84d83af7c6974f4d8ed1f3f67d1a3b42e574 Author: William Xu <william.xwl@gmail.com> Date: Mon Mar 5 04:29:00 2007 +0000 emms-lyrics.el: Fix a function name typo. darcs-hash:20070305042950-cfa61-3c32bf7ae71bbc7340928363335e1ee0172f6abd.gz commit 7a900b9da3998446b7b61fe8d17d0ea5f276ee6e Author: William Xu <william.xwl@gmail.com> Date: Fri Mar 2 14:11:00 2007 +0000 emms-lyrics.el: Add chinese lyrics lookup support to `emms-lyrics-visit-lyric'. darcs-hash:20070302141102-cfa61-314352c7bbddecdcac1c21df80e410d36b12df10.gz commit cddc8bac0335301b8c9837a6b997d09b26c943fc Author: Michael Olson <mwolson@gnu.org> Date: Mon Mar 5 14:42:00 2007 +0000 Manual: Minor fixes in new Quickstart chapter darcs-hash:20070305144251-1bfb2-b3d806d7862a34d35855cbd19dc5380221c26abd.gz commit cbbc743321cbd381562d07e4e155ffd3f2047a72 Author: Tassilo Horn <tassilo@member.fsf.org> Date: Sun Mar 4 12:49:00 2007 +0000 quickstart-guide.dpatch darcs-hash:20070304124948-c06f4-91b07cd70dad8322b75398c8b359d739f5000327.gz commit e33815846acddb8a6ee683935777403748c4a29a Author: Michael Olson <mwolson@gnu.org> Date: Sun Mar 4 07:59:00 2007 +0000 emms-player-mpd: Stylize Lisp code in documentation darcs-hash:20070304075903-1bfb2-115b9f1758a4dd677989f03493b255ae724d6b58.gz commit 53cbbecf7d49adf53b639df13df099f446f8a1ac Author: Michael Olson <mwolson@gnu.org> Date: Fri Mar 2 15:21:00 2007 +0000 emms-lyrics: Fix compiler warnings darcs-hash:20070302152148-1bfb2-a126cf94fafb664291114af7e187626aedb7466d.gz commit 9b41cd71d5ad068c02ccbfaf41cac9a7fd5e4696 Author: William Xu <william.xwl@gmail.com> Date: Fri Mar 2 10:32:00 2007 +0000 emms-lyrics.el: Rename `emms-lyrics-find-current-lyric' to `emms-lyrics-visit-lyric', and enhance it by adding searching from internet support. darcs-hash:20070302103240-cfa61-24199021412d67d4e4024b015b11cc5114f534e6.gz commit bc0a635e4f13e4b8e431cfd0cb21074fcb10e2b9 Author: Michael Olson <mwolson@gnu.org> Date: Fri Mar 2 06:58:00 2007 +0000 emms-lyrics: Fix several compiler warnings darcs-hash:20070302065810-1bfb2-6dcbd9b2f3cd32d38f4237b8f21fb8fa0dfa5f10.gz commit c1fe22499774d5ddd1ff1d13a3c7ccf68ddb1090 Author: William Xu <william.xwl@gmail.com> Date: Fri Mar 2 05:56:00 2007 +0000 emms-lyrics.el: Add lyrics auto-scrolling support. darcs-hash:20070302055649-cfa61-f0057be1f5fc594a49d1fa5f12cd2973529e8956.gz commit 01c7a23c5776a108b89c9afeb9cb51341afae2a6 Author: William Xu <william.xwl@gmail.com> Date: Thu Mar 1 09:15:00 2007 +0000 emms.texinfo: Update lyrics section. darcs-hash:20070301091537-cfa61-58e400533d2fb56d726c870ee3861981ba11a55c.gz commit bbd748ac03ad597ba7e3379c0129728b90c020bc Author: William Xu <william.xwl@gmail.com> Date: Sun Feb 25 06:13:00 2007 +0000 NEWS: Mention changes in emms-playing-time. darcs-hash:20070225061342-cfa61-104ba5e011b693cec161e8965289ebc57a1d5061.gz commit 35d850ee9ffbb2a6f5a77b9cee6d33f822485e92 Author: Michael Olson <mwolson@gnu.org> Date: Tue Feb 27 18:04:00 2007 +0000 emms-player-mpd: Miscellaneous docfixes darcs-hash:20070227180444-1bfb2-0b51168d8fcc72f778e096ffa1bfc144e6ccf6b2.gz commit 5df575f17845dc18538cc124c07fa5bdd538704e Author: Michael Olson <mwolson@gnu.org> Date: Fri Feb 23 04:08:00 2007 +0000 manual: Mention how to set the default EMMS playlist mode darcs-hash:20070223040831-1bfb2-210e874993e3389849ddcbfd68c253ac4aae3d07.gz commit 07827ace695e03d5494530fbf369e507c32c4688 Author: Michael Olson <mwolson@gnu.org> Date: Fri Feb 23 04:01:00 2007 +0000 Move dictionary definitions higher to avoid compiler warning darcs-hash:20070223040135-1bfb2-d3cb1425d6d67d9c6a43718a57fa8c04cc236ca9.gz commit 4cb782eaac1243423c82587729ccf5811b51841d Author: Tassilo Horn <tassilo@member.fsf.org> Date: Thu Feb 22 16:51:00 2007 +0000 improve-emms-mark-and-write-docs.dpatch Fixed emms-mark-track so that you can (un)mark backwards with `C-u -3 m'. Wrote texinfo docs for emms-mark.el. darcs-hash:20070222165136-c06f4-ececc4b3161d92d827588400d52ad97186a784a5.gz commit 0a2a9b02e30a9d9755102a07a41cac8bddccdab9 Author: mlang <mlang> Date: Wed Feb 21 14:05:00 2007 +0000 Speed up emms-play-directory-tree by about factor 10 Most of the speedup comes from using nconc in later-do instead of append (and therefore, not excessively copying lists). I see a factor of 10 speedup when generating the playlist for 37000 audio files. darcs-hash:20070221140553-08870-162cb94182e5e4947a0972a67b9229db8899e7cd.gz commit c042491950f6b57ff1c14d6bfd9d4f01a72d5d4a Author: Michael Olson <mwolson@gnu.org> Date: Thu Feb 15 23:11:00 2007 +0000 Fix several XEmacs compatibility issues darcs-hash:20070215231146-1bfb2-8b67281c41a771504c6549ad234eb82e26bbfc91.gz commit 4d03fc1346fbd7d191636b946b51d3ca2fea9143 Author: Michael Olson <mwolson@gnu.org> Date: Thu Feb 15 17:12:00 2007 +0000 emms-texinfo: Add stubs for emms-mark and emms-tag-editor I've added "write me" chapters to the manual for emms-mark.el and emms-tag-editor.el, because they need to be written before the release. Hopefully others will volunteer to write them :^) . darcs-hash:20070215171211-1bfb2-2fdc1a0f7226c89cdd5ab04448eaeb681d995613.gz commit bf0fdbc820a3f44740ecb1173ca8a72563b1d9a1 Author: William Xu <william.xwl@gmail.com> Date: Thu Feb 8 03:33:00 2007 +0000 Add `emms-lyrics-catchup' for dealing with external lyrics crawler. darcs-hash:20070208033306-cfa61-5ac1575c14aebd22055fcffbff41b0dff8683a46.gz commit cedb42731ca20e69409074a3faf0e292e1a70eba Author: Michael Olson <mwolson@gnu.org> Date: Wed Feb 7 14:22:00 2007 +0000 NEWS: Update darcs-hash:20070207142227-1bfb2-e564dd9726b67dceb13b1d9888881f94fc9983f6.gz commit 687746e80c5bd91cd87e62ff307386b52274fc43 Author: Michael Olson <mwolson@gnu.org> Date: Mon Jan 29 15:46:00 2007 +0000 emms-tag-editor: Make editing of ogg vorbis comments work properly It turns out we have to have the "-t" option before each bit of track information, not just the first. Also, avoid sending empty track information to vorbiscomment. darcs-hash:20070129154657-1bfb2-a8266b299f4c9eee6db666b1ff71a04c3aa48076.gz commit 0a349ff083fd9d426a3bcfa1b23ceb5b66d40f0f Author: Michael Olson <mwolson@gnu.org> Date: Mon Jan 29 15:09:00 2007 +0000 emms-mark: Save the keymap properly darcs-hash:20070129150940-1bfb2-b4756560bea0de1b19ce79f91895f1337b7eb92c.gz commit 58ee26a7819a800fc9fac3d768c79e678702dc46 Author: Michael Olson <mwolson@gnu.org> Date: Mon Jan 29 09:18:00 2007 +0000 emms-mark: Overhaul and turn into a derived mode Make emms-mark integrate better with the rest of EMMS by turning it into a derived mode of emms-playlist-mode. This allows it to have its own keymap derived from emms-playlist-mode, and be easily enabled and disabled without messing up the output from emms-show. It will operate on a buffer-by-buffer basis, but can easily be made the default playlist mode if desired. We have to avoid calling emms-playlist-mode a second time when starting emms-mark-mode, so that the selection does not disappear. Thus, it must be its own function, rather than using define-derived-mode. darcs-hash:20070129091833-1bfb2-2a879719548db4b2b8a0f143d6cb2f1ace4419ce.gz commit ae36768ee0ae1af113c60aef417b6e889f914984 Author: Michael Olson <mwolson@gnu.org> Date: Mon Jan 29 09:17:00 2007 +0000 emms-playlist: Pay attention to selection when updating Make sure that we preserve the current selection if updating the currently-selected track.. darcs-hash:20070129091716-1bfb2-a0a7e5b14cc02d29c27de5bfdb068f5b9a1b39b7.gz commit dc1f3f03fbc62baa6da7112cbdf23b9b3d50b661 Author: Michael Olson <mwolson@gnu.org> Date: Mon Jan 29 09:13:00 2007 +0000 Distinguish `emms-track-description' and `emms-track-force-description' The idea is that emms-track-force-description is only allowed to be used when inserting descriptions into a playlist buffer. This lets us distinguish between the content and layout of the text, for add-ons like emms-mark that want to do something decorative with the text. darcs-hash:20070129091330-1bfb2-efe486ed3f4b256cf5817a1b36d66448a6c14196.gz commit 5cf0ca5712443a452b77233440bb9e2cc103b6ec Author: Michael Olson <mwolson@gnu.org> Date: Mon Jan 29 09:11:00 2007 +0000 New macro emms-walk-tracks This macro makes it easy to write code which steps forward through the tracks of the current buffer iteratively. darcs-hash:20070129091141-1bfb2-feed35fa379e6424a16cd0d735fc95e3f2d9f47b.gz commit 9dd55eed355f98f163dc45fc40f61ed9cb31da0e Author: Tassilo Horn <tassilo@member.fsf.org> Date: Tue Jan 16 20:20:00 2007 +0000 restart-lastfm-plugin-when-md5challenge-expired.dpatch darcs-hash:20070116202013-c06f4-ffed46f2b4507fd4aaf9d025efd052f8f169a7c0.gz commit 1e3daf1289c4d23c2b046b212dbf7ea0a567daf3 Author: Tassilo Horn <tassilo@member.fsf.org> Date: Sat Jan 13 10:49:00 2007 +0000 fix-ampersands-and-question-marks-in-lastfm.dpatch Roman Lagunov reported a bug: the last.fm plugin failed scrobbling tracks with & in artist/title/album. The same applies to streams containing an ampersand. So I added ?& and ?? to `emms-url-specials'. But because both are needed to submit values via HTTP GET now you have to `emms-escape-url' only the arguments that may contain special chars instead the complete url, e.g.: (url-retrieve (concat emms-lastfm-server "?hs=true&p=1.1" "&c=" emms-lastfm-client-id "&v=" (number-to-string emms-lastfm-client-version) "&u=" (emms-escape-url emms-lastfm-username)) instead of (url-retrieve (emms-escape-url (concat emms-lastfm-server "?hs=true&p=1.1" "&c=" emms-lastfm-client-id "&v=" (number-to-string emms-lastfm-client-version) "&u=" emms-lastfm-username)) darcs-hash:20070113104902-c06f4-9bf8c040fff6d350a3a7dafcaf2cbf26700d2f04.gz commit 6ab92fbf3000f8c8c6443e0fa0e43dadda7ef1ae Author: Michael Olson <mwolson@gnu.org> Date: Sat Jan 13 23:48:00 2007 +0000 Manual: Add periods to end of menu entry descriptions, update menus, minor grammar and style fixes darcs-hash:20070113234824-1bfb2-da3ea7487abd550b9a8929e1e669a23aebc0395e.gz commit ffa6c3be8a1eebfd9ef04015cd1ef688d7258953 Author: Tassilo Horn <tassilo@member.fsf.org> Date: Mon Jan 8 20:59:00 2007 +0000 relative-seeking-for-xine.dpatch darcs-hash:20070108205923-c06f4-43ce67680b8401a113b4388046ef64028a2f9646.gz commit 921bc18f85725299a0ccdef54e6cda3d33afb747 Author: Michael Olson <mwolson@gnu.org> Date: Mon Jan 8 19:13:00 2007 +0000 emms-streams: Make sure type is a symbol, not a string darcs-hash:20070108191308-1bfb2-f750982c6594b9b829cf0fe07ca3a084994681ff.gz commit 816f4d8de3bb595318965d6b75af814642d58308 Author: Tassilo Horn <tassilo@member.fsf.org> Date: Sun Jan 7 10:41:00 2007 +0000 emms-volume-texinfo.dpatch Adds docs for emms-volume-minor-mode and replaces defvars with defopts in the last.fm chapter. darcs-hash:20070107104105-c06f4-9584be6b59027bb8eb58c3706271be455bd27e24.gz commit 957e445ae31727202e6a0e39fe41647b67c548b9 Author: Tassilo Horn <tassilo@member.fsf.org> Date: Sat Jan 6 17:37:00 2007 +0000 emms-player-xine.dpatch darcs-hash:20070106173701-c06f4-b2990cbad3a0c9068706fbec7ad03246ad8f3aa6.gz commit 04dcbc6f6822be6ff4be85fbbfa048735907121a Author: Michael Olson <mwolson@gnu.org> Date: Sat Jan 6 01:15:00 2007 +0000 emms-lastfm: Remove periods from end of messages darcs-hash:20070106011559-1bfb2-d2f2ae6b142c268090f8fff10aceacb1e8b30183.gz commit e8ddda19e1f8406b5a8c5c771513218b1459b734 Author: Michael Olson <mwolson@gnu.org> Date: Fri Jan 5 23:50:00 2007 +0000 emms-lastfm: Add emms-lastfm-np, which displays the current song information as a message or inserts it at point darcs-hash:20070105235058-1bfb2-35bf242a357711d2539c8d036f6ea6c8cff87957.gz commit ef7fe16f8b6a1283012099998c4abea2818abd93 Author: Michael Olson <mwolson@gnu.org> Date: Fri Jan 5 23:06:00 2007 +0000 Add support for playing Last.fm streams using emms-streams interface darcs-hash:20070105230616-1bfb2-51c5cd5cdac1b0ab9daee569c4258296a030cdf3.gz commit 11b83c0e196570462740e544d0b86bbce14a1c44 Author: Michael Olson <mwolson@gnu.org> Date: Fri Jan 5 07:39:00 2007 +0000 emms-lastfm: Use emms-cancel-timer, fix FIXME section, make emms-lastfm-radio-request-metadata more flexible darcs-hash:20070105073906-1bfb2-729fbbac890b5f735db3aa4f91679d8e611f176a.gz commit f2a4e314641d755b65b420055ebd567a5e2aac01 Author: Michael Olson <mwolson@gnu.org> Date: Fri Jan 5 07:38:00 2007 +0000 emms-url: Only escape spaces and newlines, on second thought darcs-hash:20070105073821-1bfb2-160387bb8220df00cc01d0c69d441ca34069e44d.gz commit 48b1d322af14361065d2b1b67d7817cd86b14370 Author: Michael Olson <mwolson@gnu.org> Date: Fri Jan 5 04:27:00 2007 +0000 Make jack.el use emms-compat.el rather than cl.el, and tidy up emms-compat.el darcs-hash:20070105042701-1bfb2-0883b98f76b030dc45c5c8e975df8b12f4955204.gz commit 75b1bc1069691cc53c4f3120f67289890ef2d340 Author: Michael Olson <mwolson@gnu.org> Date: Fri Jan 5 04:02:00 2007 +0000 emms-playlist-sort: Add compile-time dependency on cl.el to avoid a warning darcs-hash:20070105040231-1bfb2-5a6ad6211071315025177f1b0ff2b3e87859c24a.gz commit 2b11ce6cb085da12ba6df16f53bbc28293836db4 Author: Michael Olson <mwolson@gnu.org> Date: Fri Jan 5 03:53:00 2007 +0000 emms-lastfm: Use emms-url.el, fix compiler warnings, and be kind to the namespace darcs-hash:20070105035342-1bfb2-ec8cde77837ba0da40b1f1d0f9c143658f0e88c9.gz commit 77c1f432b3b02151c82e035ba5f354817df7d426 Author: Michael Olson <mwolson@gnu.org> Date: Fri Jan 5 03:52:00 2007 +0000 emms-player-mpd: Use functions in emms-url.el darcs-hash:20070105035233-1bfb2-6b83da8301b2ea542a061a6baab437fea1dade9e.gz commit 1e446de1aec47d258e509183d126d0341001900f Author: Michael Olson <mwolson@gnu.org> Date: Fri Jan 5 03:40:00 2007 +0000 emms-url: New file containing the url.el interaction routines from emms-lastfm.el. I plan to use these in other parts of EMMS as well. darcs-hash:20070105034035-1bfb2-d213da8dab318baf3fc5d6a1f7a3ac75d0e7640c.gz commit c744071cb69bff0a4fa7dfaf469aa1d6bb845b1d Author: Michael Olson <mwolson@gnu.org> Date: Fri Jan 5 03:22:00 2007 +0000 emms-compat: New file that contains compatibility functions for emms; this make emms.el a bit cleaner-looking darcs-hash:20070105032247-1bfb2-da5b30366dfa15a91f877cae883d7324965fec9c.gz commit 7805ee70add349cf732370fb6d23af3d5d6f5720 Author: Michael Olson <mwolson@gnu.org> Date: Fri Jan 5 00:09:00 2007 +0000 emms-streams: Try to reconnect to station if briefly disconnected darcs-hash:20070105000942-1bfb2-f536818d060661e6ace6d41cd9cbfbc6c45c47e7.gz commit 36d1fa87cb1cab51e4ccdefb56ac2c88f81a514c Author: Michael Olson <mwolson@gnu.org> Date: Fri Jan 5 00:08:00 2007 +0000 Remove emms-volume-mpd-raise/lower, make chapter in manual for emms-volume.el darcs-hash:20070105000820-1bfb2-20d9168d8cc55d2098f37602ade9aff5875b61aa.gz commit b7ea3e17a00a749e71d8f1b392b4974d1a317a52 Author: Tassilo Horn <tassilo@member.fsf.org> Date: Wed Jan 3 20:55:00 2007 +0000 artist-fan-radio-and-texinfo-docs-for-lastfm.dpatch This patch adds a new function to emms-lastfm.el: `emms-lastfm-radio-artist-fan' I also added a chapter about Last.fm in emms.texinfo. It compiles for me and looks good, but it wold be nice if someone could have a short look at it. It's my first work with texinfo. darcs-hash:20070103205523-c06f4-60d44277e0b325c4bd5bc61c4af7bed922afa1a9.gz commit ba4cd47bf818ec6fb6a75c7eab6081ed8e2a1e3d Author: Tassilo Horn <tassilo@member.fsf.org> Date: Wed Jan 3 14:07:00 2007 +0000 fix-broken-multibyte-chars-in-http-responses.dpatch If a `url-retrieve' returns a buffer containing multibyte strings, they were displayed as \123\456. The bug occured mostly when listening to Last.fm radio playing a track with non-ascii title or artist. Thanks to fledermaus at #emacs for investigating what went wrong and putting together the function `http-decode-buffer'. The bug seems to be fixed with it. darcs-hash:20070103140726-c06f4-414b42c7fba6a1587d9a6c8f0dd2de8e1ca67cc0.gz commit 8be497eb448358bcbf457bba3a28d60ea997799f Author: Tassilo Horn <tassilo@member.fsf.org> Date: Tue Jan 2 22:24:00 2007 +0000 metadata-for-lastfm-streams.dpatch Now the Artist and Title of the current song are displayed in the mode-line when listening to a last.fm stream. Additionally I made all user options customizable. darcs-hash:20070102222433-c06f4-8817244e846fa35dad3089f6f7e2796cece14d37.gz commit 55934a3e90ef9183a1065f2d4bba2d89dd4524de Author: Tassilo Horn <tassilo@member.fsf.org> Date: Sat Dec 30 11:59:00 2006 +0000 lastfm-skip-love-ban-plus-renaming.dpatch First, I renamed all things "emms-lastfm-playback" to "emms-lastfm-radio", which fits much better. Then I added the functionality of loving/skipping/banning the song you're listening to on Last.fm Radio. darcs-hash:20061230115944-c06f4-2de5c66d5c0c6e598b01d4d77d1865d9ddf76602.gz commit dbcdaf0419ef86e905b731cdc1a13de2f57b4d9e Author: Tassilo Horn <tassilo@member.fsf.org> Date: Fri Dec 29 15:59:00 2006 +0000 fix-lastfm-streams-with-spaces.dpatch darcs-hash:20061229155921-c06f4-369eab9cc2a0410ec195775bf5b7237c23bc3007.gz commit 1a233b4d1611446ed6c89025b5dfce46fdf58e30 Author: William Xu <william.xwl@gmail.com> Date: Mon Dec 25 05:45:00 2006 +0000 emms-playlist-sort.el: Reorganize codes && add `emms-playlist-sort-by-list'. darcs-hash:20061225054559-cfa61-8735b162cb04410687f89dc778115cd4a0d516ca.gz commit 4176ebe3d723201d3c3e0459fc94fe7331549519 Author: Tassilo Horn <tassilo@member.fsf.org> Date: Wed Dec 27 20:57:00 2006 +0000 play-lastfm-streams.dpatch This patch has two major parts: 1. Make emms-lastfm.el conforming to other emms plugins, meaning that there are those three user functions: `emms-lastfm' -- The usual prefix arg toggle `emms-lastfm-enable' `emms-lastfm-disable' 2. It adds the ability to play lastfm:// streams. New user functions: `emms-lastfm-playback' `emms-lastfm-playback-similar-artists' `emms-lastfm-playback-global-tag' Sadly there are 2 FIXMEs in the code: 1. Major problem: It doesn't work for lastfm urls which contain blanks. If someone is familiar with the url library, he could tell me how to fix it. (retrieving urls with whitespaces) 2. Minor problem: There's some ugly (but working) code to ensure the execution doesn't continue before a sentinel has been run. darcs-hash:20061227205745-c06f4-6dd67d84faed5fd0c40a762375c7c8bb39b22328.gz commit 7b63da0fca011201126087be1d2a86d9d3a0b074 Author: william.xwl <william.xwl> Date: Mon Dec 18 11:20:00 2006 +0000 emms-playing-time: Add stuffs for controlling displaying on mode line while still enabling emms-playing-time module at backgrond. darcs-hash:20061218112057-e8fe6-5abc7b6dbad114317d325e86851be49dc73b2cfb.gz commit afa1083ca86a64898211babf83de24295d8d13cb Author: william.xwl <william.xwl> Date: Mon Dec 18 11:17:00 2006 +0000 emms-mode-line: Rename `emms-playing-time-toggle' to `emms-mode-line-toggle'. darcs-hash:20061218111747-e8fe6-cbfad989d5a2993a12654578ab7336ff91fcb548.gz commit 9413440d6b2b5bcfdb436b36e18419f6b8180d31 Author: Tassilo Horn <tassilo@member.fsf.org> Date: Tue Dec 19 08:54:00 2006 +0000 warn-if-playing-time-deactivated.dpatch New emms-lastfm-activate warns the user if he disabled emms-playing-time completely and points him to the right docs. darcs-hash:20061219085443-c06f4-68cc025edede1f9a399e0067526f5b519a5e2e69.gz commit 1d3cb0de6c78bf62e9dca6a3c1715147da9bfc33 Author: Tassilo Horn <tassilo@member.fsf.org> Date: Sat Dec 16 13:22:00 2006 +0000 fix-regression-in-lastfm.dpatch My last path enabled emms-lastfm.el to submit tracks even if you paused them. I tested this extensively! But I didn't test if it still submits them if you don't pause it. Of course it didn't. ;-) The problem was that I rely on `emms-playing-time' to calculate when a track has to be submitted. But in `emms-player-started-hook' my new track function was run *before* `emms-playing-time' was set to 0 again. darcs-hash:20061216132209-c06f4-c25c2f5849e7492cec0cc0b95e347ce24db2a83d.gz commit 1207c51472e11e1bf937b33c706397726bc7c6c4 Author: william.xwl <william.xwl> Date: Mon Dec 18 16:05:00 2006 +0000 emms.texinfo: Update emms-playing-time info. darcs-hash:20061218160551-e8fe6-4199708e240b7df11fae762e63185913d715905e.gz commit 87b19716ffca280e6efd7258b8b27e6d53b44c75 Author: Tassilo Horn <tassilo@member.fsf.org> Date: Wed Dec 20 20:50:00 2006 +0000 replace-next-line-with-forward-line.dpatch The docstring of `next-line' suggest to use `forward-line' instead, so use that... darcs-hash:20061220205010-c06f4-2562ebd8052d536eebce9d1f6e21112f0934b3ec.gz commit 99bd78e86c37e8877178900e81dea03dcc1c0959 Author: Tassilo Horn <tassilo@member.fsf.org> Date: Tue Dec 12 20:03:00 2006 +0000 submitting-when-paused.dpatch This patch enables emms-lastfm.el to submit the current track even if the playback has been paused and resumed. It's done by canceling the `emms-lastfm-timer' when pausing and reenabling it on resume. darcs-hash:20061212200324-c06f4-2ab89e58a91532db90e54e84f209086aa28f3a7f.gz commit a0b3273c77c85c9585e84b7ba88f4928ef47267b Author: william.xwl <william.xwl> Date: Mon Dec 11 07:04:00 2006 +0000 emms-lyrics: Make `emms-lyrics-find-lyric-function' customizable and add `emms-lyrics-find-current-lyric'. darcs-hash:20061211070439-e8fe6-9a7b49afeb25197e7dc01b60aaf04a31296906d4.gz commit fc233207f029ca9642e7411e29df3b3d460943a5 Author: Ye Wenbin <wenbinye@gmail.com> Date: Fri Dec 8 05:21:00 2006 +0000 change raise/lower-function to change-functon, add change-amount darcs-hash:20061208052114-94065-3871387b8052194dc22627408e58b7822b670a10.gz commit 12d0f5f9a066637e787e2f95de687b9245785ebd Author: Ye Wenbin <wenbinye@gmail.com> Date: Fri Dec 8 05:20:00 2006 +0000 Remove emms-volume-amixer-raise/lower commands, use emms-volume-change-function darcs-hash:20061208052019-94065-5be6631013ce5b2e97279fd97caeb54c6a254c0a.gz commit 1c6cb9eb79a794ad30f358a1fa3fd15ce989fc58 Author: william.xwl <william.xwl> Date: Fri Dec 8 03:13:00 2006 +0000 emms-i18n: Rename functions to match file name. darcs-hash:20061208031325-e8fe6-a68edcc4f273b4583675ef3d0a0bc00a66119e05.gz commit cb267393281a2b75f699bf324a4be1baf37e7c72 Author: william.xwl <william.xwl> Date: Fri Dec 8 03:12:00 2006 +0000 emms-setup: Add `emms-i18n' to `emms-devel'. darcs-hash:20061208031213-e8fe6-b243cd4fb74540e94cec5e5df389fc4b7c10f0ce.gz commit 13525d2c4185d0bf2bad4f9518b8a355ec745f62 Author: william.xwl <william.xwl> Date: Fri Dec 8 03:10:00 2006 +0000 emms-info-mp3info: Make use of `emms-i18n-call-process-simple'. darcs-hash:20061208031029-e8fe6-fdb07b59286e2152d399670e2881a6648a17c887.gz commit a33416f6dcf0f9212b5680c814ce21b2c3315480 Author: Michael Olson <mwolson@gnu.org> Date: Fri Dec 8 22:35:00 2006 +0000 emms-player-mpd: Document how to use MusicPD to change the volume via emms-volume.el darcs-hash:20061208223509-1bfb2-9566bd733009216ccf1b12e5c3ca17cc67db8d4e.gz commit 3c42fe2cc29a102faddc818a74fac9dfe34bbeac Author: Michael Olson <mwolson@gnu.org> Date: Thu Dec 7 14:35:00 2006 +0000 Fix various byte-compiler warnings throughout darcs-hash:20061207143511-1bfb2-90e8bee5074d6ef5ca4c9998886d28eedf6df671.gz commit a37a70fffeeb70f42964a3d24d508c32eee2ec0b Author: Michael Olson <mwolson@gnu.org> Date: Thu Dec 7 14:23:00 2006 +0000 emms-tag-editor: Rename functions to match file name darcs-hash:20061207142310-1bfb2-3dda8c692c17a031f70477aa2597ef161f420780.gz commit e73db75f5474190399ab6d340cc9c8e0a8e78d6c Author: Michael Olson <mwolson@gnu.org> Date: Thu Dec 7 14:19:00 2006 +0000 Rename emms-mp3tag.el to emms-tag-editor.el darcs-hash:20061207141945-1bfb2-bec40763ab0162499c3829e073717915ba509653.gz commit 2adff3ed4e9dabb25680880df66b7e67b9f635bb Author: forcer <forcer> Date: Thu Dec 7 09:46:00 2006 +0000 emms.el: Improve `emms-uniq-list' to not use cl.el. darcs-hash:20061207094656-2189f-b0e45986b49ad8a3f15f50c57a80cf644608f428.gz commit ea35b0637aff4d1f61dac2d25b6556a4d939e6b4 Author: Ye Wenbin <wenbinye@gmail.com> Date: Thu Dec 7 06:35:00 2006 +0000 emms-i18n changes, add playlist navigate command, uniq playlist command darcs-hash:20061207063510-94065-7726a0fc26d04c70038d5576a0a1451e7e71e368.gz commit d87cd1c3112c9e916fc71fd41721726709cae7c0 Author: Ye Wenbin <wenbinye@gmail.com> Date: Wed Dec 6 15:35:00 2006 +0000 emms-mp3tag support ogg, add more documentation. fix some error darcs-hash:20061206153528-94065-1a7c6b96e2ae32e1f02b97bc884be6540021f21f.gz commit 6d534076968d10556180d767d1af351b73fe2440 Author: Tassilo Horn <tassilo@member.fsf.org> Date: Wed Dec 6 11:28:00 2006 +0000 emms-lastfm.dpatch This patch adds emms-lastfm.el, its setup to emms-setup.el and myself to AUTHORS. darcs-hash:20061206112823-c06f4-5194a01ee6fb3e33c67788f3cb884fe8a3123bb1.gz commit cdf083c2e7cf292d0aa784829474694c73ba7ba7 Author: Ye Wenbin <wenbinye@gmail.com> Date: Wed Dec 6 02:07:00 2006 +0000 Fix a silly bug in emms-mp3tag. Remove timestamp. darcs-hash:20061206020710-94065-9f1c251e33352a0f5bec560bd0d6d82c2d637f39.gz commit d8c405fd97a4d3cf1aedfb78af3d0484100e8be3 Author: forcer <forcer> Date: Tue Dec 5 22:49:00 2006 +0000 AUTHORS: Added Ye Wenbin darcs-hash:20061205224950-2189f-e5098ca4eade05eac0461aeb2542adf4d115fdf8.gz commit 3ba64d032d74107a7e0cbaf376a6d803b0883db9 Author: Wenbin Ye <wenbinye@gmail.com> Date: Mon Nov 27 15:41:00 2006 +0000 Fix lyrics minibuffer display. Amixer display playback and more useful commands darcs-hash:20061127154113-1e472-b3fb81d5e2e6e3669932a4927e30d18f2cb118da.gz commit 358e193b021835ff0b9de91b35959ed518bb9455 Author: Wenbin Ye <wenbinye@gmail.com> Date: Tue Dec 5 11:22:00 2006 +0000 Edit all track, set tag to file for mp3 darcs-hash:20061205112209-1e472-cf5affbb0fb48365d3db39f0fe87e5ebb68d0ec6.gz commit dfe998b5663c2288a7c01dfbde6afead4e554cd3 Author: Wenbin Ye <wenbinye@gmail.com> Date: Tue Dec 5 06:54:00 2006 +0000 Add emms-mp3tag and emms-i18n darcs-hash:20061205065407-1e472-4680607fa20dfb5e818879d67781d1379602d473.gz commit 557b66c48ac913b29028394a10f836e6022d21e9 Author: wenbinye <wenbinye> Date: Tue Nov 21 09:39:00 2006 +0000 Add emms-mark and emms-history darcs-hash:20061121093951-08d48-1f8e847e723722158371686a8e237205a2d8eae0.gz commit 3b044df7a4b8ccee82809e548692d89e901af8ef Author: william.xwl <william.xwl> Date: Mon Nov 20 07:58:00 2006 +0000 emms-info-mp3info.el: Replace `emms-iconv' with decode-coding-string and encode-coding-string. darcs-hash:20061120075851-e8fe6-1d71baea3e9f557b21be05f8798b7b91b1f35b9b.gz commit 4cc64352f52a7e255cdc57d51682f280fec5c7e6 Author: Michael Olson <mwolson@gnu.org> Date: Sun Nov 19 20:47:00 2006 +0000 emms.el: Fix bug introduced by recent changes to emms-playlist-set-playlist-buffer darcs-hash:20061119204738-1bfb2-1d4b04cebe07ed71813341c71a9e004bff2b898f.gz commit 343599d4750a34142fc6e230f845a24933220d3e Author: Michael Olson <mwolson@gnu.org> Date: Sun Nov 19 05:34:00 2006 +0000 Default to current buffer when setting the current EMMS playlist buffer. darcs-hash:20061119053410-1bfb2-9cb15edee05a30c8a3b85865a0cfbd2f5f7302be.gz commit 76ab749162ef9cf8a782b0d801645b94a9e80a49 Author: Michael Olson <mwolson@gnu.org> Date: Sun Nov 19 05:29:00 2006 +0000 manual: Add documentation for new emms-playlist-mode keybindings darcs-hash:20061119052935-1bfb2-b57a2317cb13452e6a57cdae3162d203a6c7c3b8.gz commit 389f8e9cebf540cf75d12a34503b90ff59c48d6b Author: Michael Olson <mwolson@gnu.org> Date: Sun Nov 19 05:29:00 2006 +0000 emms-playlist-mode: Bind "b" key to emms-playlist-set-playlist-buffer. darcs-hash:20061119052907-1bfb2-ff79f861aeed682d752a27fcd7263b9793e7fa19.gz commit 89dfb1711522d10f8af645caca40663c1f8c6ac8 Author: Michael Olson <mwolson@gnu.org> Date: Sun Nov 19 05:22:00 2006 +0000 emms-playlist-mode: Implement adding the thing at point to the current playlist. If it is a playlist, add its contents instead. Map this to the "a" key. darcs-hash:20061119052254-1bfb2-46e03e36bd085c65c8ba9704a7c7eca29717b653.gz commit b19d65da017e9a95fd018bf1c205f5d18b95ce8f Author: Michael Olson <mwolson@gnu.org> Date: Sun Nov 19 05:20:00 2006 +0000 emms.el: In emms-playlist-set-playlist-buffer, prompt user from available EMMS playlist buffers rather than all buffers, and display feedback upon setting the current buffer, since this is not an easy change to see darcs-hash:20061119052023-1bfb2-145fb4f51da6d1bff473343442ddb9ea207ffded.gz commit b4b5e24a6ce5b7049a95ddc66949b7b1d1b99d67 Author: Michael Olson <mwolson@gnu.org> Date: Sun Nov 19 05:19:00 2006 +0000 emms.el: Fix compiler warning darcs-hash:20061119051946-1bfb2-780c256c18693a4e5af05fc01d7c04320d9afd1d.gz commit 308290aa272fff106c81d1f4ae51b76190d8fe12 Author: Michael Olson <mwolson@gnu.org> Date: Sun Nov 19 04:19:00 2006 +0000 Don't add subdirectories for directory and playlist-directory source insert methods darcs-hash:20061119041900-1bfb2-8adccc41afb392449ac47e4c216d26d640d6b4d5.gz commit 35728800bcb93f1078d0d3c72b769b9010e2ab8a Author: william.xwl <william.xwl> Date: Sun Nov 12 12:33:00 2006 +0000 emms-playing-time.el: New variable `emms-playing-time-style', it supports two styles at present, `time' and `bar'. darcs-hash:20061112123308-e8fe6-144635260d3ece1eae45593f6900478b4f089bc2.gz commit de7f530b99b24ff4d1e2611fddd23a9e5882422a Author: yoni-r <yoni-r> Date: Mon Nov 6 14:30:00 2006 +0000 bind SPC to `scroll-up' in emms-playlist-mode and update manual. darcs-hash:20061106143048-85c19-3d182e8db9986ecaa1780b823ef9cc55a4ea3592.gz commit 2859ed4a7c7ab97cf0f56d508b8e6b328e059e9c Author: forcer <forcer> Date: Wed Oct 25 17:51:00 2006 +0000 emms.el: Move macros to the top of the file. darcs-hash:20061025175106-2189f-b5e2b3e02e577abf79fac5c99bb2869f7582dbb5.gz commit 59cc07ba42ed34d1aa83c01fec576d93cdb903d6 Author: Michael Olson <mwolson@gnu.org> Date: Sat Oct 28 04:21:00 2006 +0000 emms-player-mpd: Deal with change in output when getting supported file types darcs-hash:20061028042119-1bfb2-ac4774e6e82e7c4a15626c99d33efaa378d5e5a0.gz commit 189556320ffc56d9489fb68f217707855757702c Author: Michael Olson <mwolson@gnu.org> Date: Mon Oct 23 12:57:00 2006 +0000 NEWS: Add entry for recent emms-player-mpd change darcs-hash:20061023125738-1bfb2-9f4470fe0170171eb6d34b06ae443db4ac8809c9.gz commit a639b45e90875355321ac66cbd2a79246e01f214 Author: forcer <forcer> Date: Mon Oct 23 02:03:00 2006 +0000 NEWS: Version 2 is version 2.0 darcs-hash:20061023020321-2189f-a11a98126a3de5d70517a1a4e9c82fd00e182cfd.gz commit a5451614ebb9ee9d5a45751ac24eba15fe9b96af Author: Michael Olson <mwolson@gnu.org> Date: Sun Oct 22 21:53:00 2006 +0000 emms-player-mpd: Handle errors that occur when we begin playback darcs-hash:20061022215310-1bfb2-b99b27d89e83a9657f43100cdae95791c4409dab.gz commit c3e08253a22aaa9ba3eba33178168da689fa87e2 Author: Michael Olson <mwolson@gnu.org> Date: Sun Oct 22 20:17:00 2006 +0000 emms-playlist-mode: Handle case where selection has not been set but user wants to delete a region darcs-hash:20061022201724-1bfb2-58bd537d09c2f5bb2d6c70e72ed125488a7b24d8.gz commit 80454515b177a5883118586aeea95b9007c84ced Author: william.xwl <william.xwl> Date: Sat Oct 21 06:23:00 2006 +0000 emms-player-mplayer.el: Mplayer also supports .vob files. darcs-hash:20061021062319-e8fe6-cc708b808381325149b0845d6778778afd33a65f.gz commit 695ddd235e6df10b32a9d8ed460e10f8e56e52c4 Author: mlang <mlang> Date: Sun Oct 15 19:41:00 2006 +0000 FluidSynth midi file player darcs-hash:20061015194104-08870-0cf34454c85441753986c50f8ce4bb47da88a69d.gz commit d0b80b40d9e5cf36820d42d45a516be6d6070a3c Author: forcer <forcer> Date: Sat Oct 21 15:12:00 2006 +0000 Added delYsid darcs-hash:20061021151250-2189f-b65dae315c48c2e6d997bbcbacadb74b7bbb1812.gz commit 36365442bce62e58f991a5e3e33ba49283915ed0 Author: mlang <mlang> Date: Sun Oct 8 15:20:00 2006 +0000 jackd-support-for-emacs jackd is a pro-audio server which can be used as a backend for alsaplayer, mplayer, and lots of other linux audio apps. This module allows to start jackd from within emacs, and connect/disconnect jack client ports. darcs-hash:20061008152002-08870-a537017dd29dd4f3806da45c2e0c75dcdbb6dc8b.gz commit 59afb287740909c01497948cb72064deb136ced0 Author: Damien Elmes <emms@repose.cx> Date: Wed Oct 11 15:15:00 2006 +0000 browser: ensure the RNG is seeded before use darcs-hash:20061011151535-4e3e3-d1c70d60b24a467a346f16c8423fd2812a1378ed.gz commit 088a174bf4f6d515bc2a30e86f8624042a3171e2 Author: Damien Elmes <emms@repose.cx> Date: Tue Oct 10 12:57:00 2006 +0000 browser: require sort (fixes bug with sort-fold-case being void) darcs-hash:20061010125718-4e3e3-f4ef22e88a7b1dd89db169ec1acaff6a1998519b.gz commit 2293b9fe0a7757162ba74c5cddc47bde79c8d1e5 Author: Michael Olson <mwolson@gnu.org> Date: Sun Oct 22 02:28:00 2006 +0000 emms-playlist-mode: Fix typo in hook name darcs-hash:20061022022812-1bfb2-56bf75c18981a67d77d009158d7f38efae69bce4.gz commit 5587272ee064832f5901479bb1da12d6dd6f1210 Author: Michael Olson <mwolson@gnu.org> Date: Sun Oct 22 01:22:00 2006 +0000 emms-player-mpd: Update version recommendation darcs-hash:20061022012223-1bfb2-b9ffb934c2cdf8f1516c35b12bc00ca6f9f6266c.gz commit 40b6275d283d85095f4f23d54ac57adbc49082f9 Author: Michael Olson <mwolson@gnu.org> Date: Sun Oct 22 01:10:00 2006 +0000 emms-player-mpd: Work properly with tracks inserted by emms-browser darcs-hash:20061022011050-1bfb2-eac272f7163adf59d75547e7e4e81fd999d28ace.gz commit e188a35955432a36d91fa49792c599a176b8554e Author: Michael Olson <mwolson@gnu.org> Date: Tue Oct 17 22:21:00 2006 +0000 Add NEWS items since version 2.1 darcs-hash:20061017222117-1bfb2-6b652a1d66f71e41b47db0f41d0bea20ca11409c.gz commit b5be2839b49dd87845738557d87ca6855ef81856 Author: Michael Olson <mwolson@gnu.org> Date: Tue Oct 17 22:04:00 2006 +0000 emms-player-mpd: When using the emms-volume interface, allow the user to specify the amount of change in the volume darcs-hash:20061017220404-1bfb2-816cd9b19dfb4094787434034e46fddce4442831.gz commit 236ca21937c7fb3ca17753ccb74f2ad455e81907 Author: Michael Olson <mwolson@gnu.org> Date: Tue Oct 17 21:53:00 2006 +0000 Documentation cleanups in emms-player-mpd and emms-source-playlist darcs-hash:20061017215345-1bfb2-5b89694555857fdfa14f43aa1c62f17cd612287a.gz commit 6db74368f95169f2122667d2c436199f4861fc7d Author: Michael Olson <mwolson@gnu.org> Date: Tue Oct 17 21:02:00 2006 +0000 Since emms-player-seeked-to-functions and emms-player-time-set-functions hooks do the same thing, replace the former with the latter darcs-hash:20061017210238-1bfb2-bdadf89a3b753c5704e7252ff21d87ae6c59d79d.gz commit 3d79cae684692c04a4555b6f02a9639ec2c69031 Author: Michael Olson <mwolson@gnu.org> Date: Tue Oct 17 20:53:00 2006 +0000 emms-browser: Fix compiler warning darcs-hash:20061017205310-1bfb2-3432e0fc0cd15b1143bbec337cddc5f4e6707da8.gz commit e64ea8d75164f4788c39230a4c0bc87894bd9ed6 Author: Michael Olson <mwolson@gnu.org> Date: Tue Oct 17 20:51:00 2006 +0000 emms-player-mpd: Implement seek-to support darcs-hash:20061017205106-1bfb2-d01f0f9e55a027a2f9a9467b7544bdc6df4cfa39.gz commit 2b38de90f0691656e5f07e32a651a2816c8150e1 Author: yoni-r <yoni-r> Date: Sat Oct 7 06:47:00 2006 +0000 fix faulty emms-playlist-mode keybinding, fix due to William and Damien. darcs-hash:20061007064730-85c19-95f45dc5e099aaddb1c507fdac03311d06317de8.gz commit ab8ce99964f7eaf092fa72150257d8cbf26e9c09 Author: yoni-r <yoni-r> Date: Fri Oct 6 18:01:00 2006 +0000 Added seeking to the playlist keymap, and updated the manual. darcs-hash:20061006180139-85c19-2f2a9a09d7bf8b1c9096d80379b90e97befe1f28.gz commit 0c4b2d14c042f9d5bb044019822018eb0dfe4408 Author: Michael Olson <mwolson@gnu.org> Date: Wed Oct 4 03:22:00 2006 +0000 emms-player-mpd: Only display error if we are certain that url.el is not up-to-date darcs-hash:20061004032213-1bfb2-090d7e68e56bc4639df136e47a67c5b0966fd9c0.gz commit 2e8093272bef16a36d8e0164fe6e7ebb00a9e775 Author: mlang <mlang> Date: Fri Sep 29 22:15:00 2006 +0000 seek-for-alsaplayer Add relative seek support for alsaplayer darcs-hash:20060929221527-08870-4f515bbd69389f261ffefdef0a295c54594c194d.gz commit 3e77f17447d5094f3b3711ed391dceb71639fad5 Author: mlang <mlang> Date: Fri Sep 29 23:14:00 2006 +0000 midi-files-via-timidity A simple-player definition for timidity darcs-hash:20060929231452-08870-791180c4ae2db7c713362b97bc4053c22e3c4888.gz commit 85e1c989efd01fb21f31488ab6d10035b84cb485 Author: william.xwl <william.xwl> Date: Fri Sep 29 08:19:00 2006 +0000 emms-playing-time.el: Minor cleanups. darcs-hash:20060929081908-e8fe6-f709c35fd9e891da05ac0b55e311afe7f3fc639b.gz commit b492ffd66b8e08ffccc73f13d6d162bfd266982f Author: william.xwl <william.xwl> Date: Fri Sep 29 08:17:00 2006 +0000 emms-lyrics.el: Minor Cleanups. darcs-hash:20060929081721-e8fe6-29086db85a21f4bef4513670cdcc64bf8d64e427.gz commit 7b7a768aef113ce97c36f989d3e59acf48696ea6 Author: mlang <mlang> Date: Thu Sep 28 21:15:00 2006 +0000 pause-for-alsaplayer Get pause/resume working for alsaplayer darcs-hash:20060928211555-08870-3dc3638f98fa28d080d98d4fbb874ef2afa68af9.gz commit 7185a592e9276a5593d35cb1f4222d169516404b Author: mlang <mlang> Date: Tue Sep 26 12:49:00 2006 +0000 mms-for-mplayer mplayer also supports mms:// URLs darcs-hash:20060926124951-08870-47ed08213b018d8ed9e0ba951e9099f63a07c417.gz commit dc0f30f3eeb9ece27f60537ad5d0160045308ae5 Author: yoni-r <yoni-r> Date: Tue Sep 26 07:15:00 2006 +0000 DoTheRightThing with player pausing and emms-bookmarks.el darcs-hash:20060926071538-85c19-18986d89ae4cb5463db57249c4ee0ef5f2360cbc.gz commit 03bc583073b06d1f2b36c62227d8d0d59ea4aa36 Author: yoni-r <yoni-r> Date: Sun Sep 24 14:18:00 2006 +0000 Added emms-bookmarks.el darcs-hash:20060924141826-85c19-ac8a381dd9f8ddf8e0a9f2c358736bbcd55455f8.gz commit f9e09deb8927418fafeafa42fb838ffad2e35c28 Author: yoni-r <yoni-r> Date: Mon Sep 25 20:20:00 2006 +0000 Added `emms-pause' to emms-playlist-mode.el bound to to ``P''. darcs-hash:20060925202010-85c19-07f63a962f5850d850715f34921208a4622f757d.gz commit 8bd85e154ad7da1779fcfaf91a8c7743d20ecd2a Author: Damien Elmes <emms@repose.cx> Date: Sat Sep 23 05:11:00 2006 +0000 browser: add deletion started/finished message darcs-hash:20060923051128-4e3e3-af24f19990051bdf02f145153edff3b0a3663057.gz commit 08c21bcf7566900c9061ef848f519f4188d4fb0d Author: yoni-r <yoni-r> Date: Sat Sep 23 21:04:00 2006 +0000 Added a link to the online version of the manual. darcs-hash:20060923210401-85c19-d9047936f2de25924bd1f4a38f3390d62f48ec78.gz commit 794a5abbd8e35458d0e6a6d2ce013205eefceb26 Author: yoni-r <yoni-r> Date: Fri Sep 22 09:47:00 2006 +0000 emms-playing-time.el now works with `seek-to'. darcs-hash:20060922094757-85c19-fbb086056c6b7050585a8ad86996d39c2a8085e4.gz commit 876bc87c3b24ee8dea7fe697d1b0f127ed16621b Author: yoni-r <yoni-r> Date: Fri Sep 22 08:55:00 2006 +0000 Added `seek-to' to emms.el and emms-player-mplayer.el. darcs-hash:20060922085513-85c19-7ae430e7e6945666cef8fce5ba13d82bd669e0c8.gz commit f71dc5daf9eec2626f49250c2c703a5d6993696e Author: Damien Elmes <emms@repose.cx> Date: Fri Sep 22 09:05:00 2006 +0000 browser/cache: support deleting files, make emms-cache-dirty a defsubst darcs-hash:20060922090553-4e3e3-e2dda4ec007268376de845784060dd2af083c2a0.gz commit fe7e71377c1794b0378690e1e5ea0e0c598c53ed Author: forcer <forcer> Date: Sun Sep 3 11:57:00 2006 +0000 Release 2.1 version update darcs-hash:20060903115710-2189f-5eea9188fc963e1bd36d9343d5583df08790cdeb.gz commit 170f12730093f8a42981c926ff62c5e2df93ffac Author: Michael Olson <mwolson@gnu.org> Date: Fri Aug 25 20:32:00 2006 +0000 emms-player-mpd: Use regexp-opt instead of mapconcat. darcs-hash:20060825203258-1bfb2-8be4ed4794be6581c6a1b65dfbbfdc991a826225.gz commit fa598825e414642e9092f93cde236052c7141827 Author: Michael Olson <mwolson@gnu.org> Date: Sun Aug 27 05:21:00 2006 +0000 Include the tq.el file from Emacs 22 with EMMS, instead of re-implementing it in emms-player-mpd.el. darcs-hash:20060827052155-1bfb2-b2b47f20d03eaa85cecdf3c1805279edc59c68ee.gz commit 2f052eb2aae8ff9ee72129cda8d3bc84fb80c354 Author: Damien Elmes <emms@repose.cx> Date: Thu Aug 24 13:11:00 2006 +0000 browser: don't scroll the playlist to the bottom when switching back darcs-hash:20060824131135-4e3e3-e7ea20e0db889f22d84485d8ed6cbdcb107c11bf.gz commit c4b4668ceeebdb1b76d6a2707126c3369676b9b6 Author: Damien Elmes <emms@repose.cx> Date: Thu Aug 24 03:05:00 2006 +0000 browser: pitchfork's search page has changed darcs-hash:20060824030539-4e3e3-8b7024a3ee5e81a95bc340dd3652f5f1f313093e.gz commit 974d2130b9e2a8b4393cbed4af5365536ffe5619 Author: Michael Olson <mwolson@gnu.org> Date: Tue Aug 22 13:06:00 2006 +0000 Fix compilation warnings and don't clobber namespace darcs-hash:20060822130608-1bfb2-c2a7fc4a64e0c781bb8727f4a70efbd72e3e3d0c.gz commit 789b5f8eb5577e680f10d8c46fe51abf2ea1385d Author: Damien Elmes <emms@repose.cx> Date: Tue Aug 22 10:05:00 2006 +0000 browser: few compat fixes for emacs21 darcs-hash:20060822100508-4e3e3-a39abae41dd60465fd9e52c1c3214cb1e20f0a1b.gz commit 3b214b84cf3c84fa4147bcb0adca9c4f0d3dbb9e Author: Damien Elmes <emms@repose.cx> Date: Sun Aug 20 13:18:00 2006 +0000 manual: fix a spelling mistake (thanks yrk for adding the browser!) darcs-hash:20060820131856-4e3e3-ce86c09d286265c812d12a3a9ff2167dfe554116.gz commit fa98eb12445e29c70170a7e9c9ed12cdec008615 Author: yoni-r <yoni-r> Date: Sun Aug 20 12:47:00 2006 +0000 added the emms browser to the manual darcs-hash:20060820124739-85c19-933b5171ab5d6636ef9c2fbe494a0f8a39fde146.gz commit 79cff8d3c5c902ecae43bf8b15022f9aad4f1f52 Author: Damien Elmes <emms@repose.cx> Date: Sat Aug 19 17:52:00 2006 +0000 browser: move from emms-devel to emms-all darcs-hash:20060819175220-4e3e3-b5e03ae3d5353818d15e0fde94325d2adca6a5a3.gz commit 850a7e4e620e725f843a9e20aa36a74f01535c03 Author: Michael Olson <mwolson@gnu.org> Date: Fri Aug 18 05:05:00 2006 +0000 emms-player-mpd: Get rid of error messages when closing the MusicPD process after playing the last track in the playlist. darcs-hash:20060818050516-1bfb2-a4d4b8d0a41a68014e7c5edb6e98a2f4ea3f48ec.gz commit c211b7b5f94e0b34a78fe76f9a614203cd36e97d Author: william.xwl <william.xwl> Date: Thu Aug 17 17:07:00 2006 +0000 emms-score.el: Make use of `emms-player-next-function'. darcs-hash:20060817170709-e8fe6-eabe7a65e792a2733c9b6fe9fbfc51d2f00a84ba.gz commit 1100c55965f7e0c41dd1530eeb62f31635019a9d Author: Damien Elmes <emms@repose.cx> Date: Thu Aug 17 16:00:00 2006 +0000 browser: only display '. ' if there's a valid track number darcs-hash:20060817160007-4e3e3-dff1f93f7c5486199c6aa3116ff80ac627beaca3.gz commit d85ede8a7d0e4bbdcc35b33fad617be513618dcb Author: Damien Elmes <emms@repose.cx> Date: Thu Aug 17 15:45:00 2006 +0000 browser: add documentation for a bunch of features darcs-hash:20060817154518-4e3e3-cb7c1fcbe6a2cc19e79d941a4be82e80f65cd999.gz commit 86d376246947c648966c964107ed299c098954ba Author: forcer <forcer> Date: Thu Aug 17 16:14:00 2006 +0000 emms.el: Provide and use `emms-player-next-function'. darcs-hash:20060817161404-2189f-ed62b83d52ce9be935539a060f89a884cf7ef694.gz commit d3ff5574520143fdf7a00a0637d31f9ba5a3ded4 Author: Damien Elmes <emms@repose.cx> Date: Thu Aug 17 14:40:00 2006 +0000 browser: add last-played support You can now define filters to display only tracks played in the last week, month, etc. darcs-hash:20060817144049-4e3e3-e8f9ab27cf63a86ab6c0070fbee65c004cd08b28.gz commit 293c5bc7c2208467f4297e3ff56707a031b56f38 Author: forcer <forcer> Date: Thu Aug 17 01:56:00 2006 +0000 The coding system of choice is utf-8, not legacy-1 darcs-hash:20060817015611-2189f-ab42d5ff0cd4b473ab6bcf755ec6daade2920569.gz commit 7905db151bd394f07819ee8f43f876ae3246e58c Author: forcer <forcer> Date: Wed Aug 16 00:24:00 2006 +0000 AUTHORS: Removed zeus, he said he never did anything big to emms, only mp3player, and that code is long gone. darcs-hash:20060816002434-2189f-c9499519fbb401fc2b357d2834578e0f58b1ae78.gz commit 8bc775c9d178e5c64fc7b377e668b39414b127ba Author: william.xwl <william.xwl> Date: Sun Aug 13 17:15:00 2006 +0000 emms-info-ogginfo.el: Add check for retrieving ogginfo. darcs-hash:20060813171527-e8fe6-7d86d1ced2affec422819799253f818c5c5e717e.gz commit 043320f4cb7dd763ffe6df95b0f1c68ecf7f82f2 Author: yoni-r <yoni-r> Date: Sat Aug 12 19:49:00 2006 +0000 added emms-with-excluded-directories to emms-source-file darcs-hash:20060812194959-85c19-4195c0957541a78db68c51bf31adcb5e58a67923.gz commit 09ec5bcfdd5320369ce49919e33d7048280af450 Author: Michael Olson <mwolson@gnu.org> Date: Fri Aug 11 18:58:00 2006 +0000 emms-player-mpd: Really kill the client process, as documented, instead of waiting for it to time out. darcs-hash:20060811185849-1bfb2-bcfc45ae54e42ad5c182bd7f3cd4b6ca5e76f3f3.gz commit edbaced4c24d099692a525580d4bf853712b1bdc Author: Michael Olson <mwolson@gnu.org> Date: Fri Aug 11 18:48:00 2006 +0000 emms-player-mpd: Make supported formats regexp customizable. darcs-hash:20060811184859-1bfb2-bec436303736ffda13cfffeb7a0eea38de054894.gz commit 936e11ed52318d04470867b33d1128632f439354 Author: Michael Olson <mwolson@gnu.org> Date: Sun Aug 6 02:26:00 2006 +0000 emms-playing-time: Don't require emms-info-mp3info, since none of its functions are used directly. darcs-hash:20060806022659-1bfb2-85b04367707b2a25c93ed9d1f6b7b38c434c5fcb.gz commit f10a13c62289f54556edfa642e4e266f12e22396 Author: Michael Olson <mwolson@gnu.org> Date: Sun Aug 6 02:26:00 2006 +0000 emms-player-mpd: Emacs21 fix. darcs-hash:20060806022640-1bfb2-a9c4a3d651c91ec8e1cf49e5efaa64fafa2bf7d6.gz commit 3bcb9452259783c843444e0342468d2b566ab38f Author: Michael Olson <mwolson@gnu.org> Date: Fri Aug 4 18:53:00 2006 +0000 emms-player-mpd: Use better logic for last patch. darcs-hash:20060804185308-1bfb2-ae78a2fb0939d2265454d088eee6881b780f89be.gz commit 1359311d1d86162b1e0374afdc0dc28a9cd1d9eb Author: Michael Olson <mwolson@gnu.org> Date: Fri Aug 4 18:38:00 2006 +0000 emms-player-mpd: Correctly fetch track data when using remote MusicPD server. darcs-hash:20060804183813-1bfb2-57e60908847a03eade1622689660cf2614d219e7.gz commit b42027e47722f2c038ad455b6ca18f0b9c115643 Author: william.xwl <william.xwl> Date: Sat Aug 5 00:43:00 2006 +0000 Set correct SEPARATORS parameter for split-string. darcs-hash:20060805004338-e8fe6-e3c3067cd72a36343c35677bea69248404e0758c.gz commit 4150a25e6930608c8a6f04bc948f7c376b39dddf Author: Michael Olson <mwolson@gnu.org> Date: Thu Aug 3 03:00:00 2006 +0000 emms-player-mpd: Use better algorithm to detect whether the user has requested a stop or whether we have run out of tracks. Thanks to dds for the report. darcs-hash:20060803030044-1bfb2-8ae4e59fcafcbfff9b8b2e764aceb82d80c16faf.gz commit 88658d69d9b9ad2c9b4ad00b199bd80d93b4d534 Author: Michael Olson <mwolson@gnu.org> Date: Wed Aug 2 03:50:00 2006 +0000 emms-cache: Replace use of 'utf-8 with emms-cache-file-coding-system. darcs-hash:20060802035000-1bfb2-2f38291ea17ecbe96f1906b25c1ce147701b3ea4.gz commit 6abd26a03f3af8d76806abac5d210252bffbd088 Author: Michael Olson <mwolson@gnu.org> Date: Tue Aug 1 02:41:00 2006 +0000 emms-cache: Change default coding system to utf-8. Fix byte-compilation warning. darcs-hash:20060801024119-1bfb2-ddb4d405acf76fcaa777d4c9a359981bbe015357.gz commit d10458058daca7b53074a3d6d8a297630e2ea288 Author: william.xwl <william.xwl> Date: Mon Jul 31 17:05:00 2006 +0000 emms-info-mp3info.el: New function, emms-iconv, for converting string between different coding systems. The conversion is necessary when emms-info-mp3info-coding-system is different from emms-cache-file-coding-system. darcs-hash:20060731170503-e8fe6-0db1b71cfdc7dc39687c9b5297351541e436e8bf.gz commit 43c306146f67f59f89d262e9b91c3d21bd6910a1 Author: william.xwl <william.xwl> Date: Mon Jul 31 17:00:00 2006 +0000 emms-cache.el: New variable, emms-cache-file-coding-system, which will allow user to set cache file's coding system explicitly. darcs-hash:20060731170049-e8fe6-6d125ca38a3a3d1b1271aeeb9815b6b8a0411c58.gz commit f7d41460d9077b0c553d63f17c702c659e3d53ee Author: Michael Olson <mwolson@gnu.org> Date: Sun Jul 30 22:31:00 2006 +0000 emms-player-mpd: Add support for updating MusicPD's database and improve documentation. darcs-hash:20060730223147-1bfb2-5e323fa65ecb32976db21c07a96143d36d65d7e8.gz commit aa9c184f2e41d831bed2c209112f4299ce27f58a Author: Michael Olson <mwolson@gnu.org> Date: Sun Jul 30 22:02:00 2006 +0000 emms-streams: Don't prompt for fd. Determine it automatically instead. darcs-hash:20060730220232-1bfb2-788a8edc59ad10890149cadd420b2ec7cf87defc.gz commit ab3184047fd4ff9373bacccd8f583674ba738849 Author: Michael Olson <mwolson@gnu.org> Date: Sun Jul 30 21:50:00 2006 +0000 emms-player-mpd: Allow a password to be sent to the MusicPD server. darcs-hash:20060730215000-1bfb2-492d75142915235bcc52d20e92d7d9973dfd8053.gz commit 9e243bd6c4fdc71083203116d98af41ba00851ea Author: Michael Olson <mwolson@gnu.org> Date: Sat Jul 29 02:25:00 2006 +0000 emms-info: On second thought, with remote players, info should be fetched even when the file does not exist on the local system. So we should always fetch info when file-mtime is nil. darcs-hash:20060729022523-1bfb2-edf73ea0c2e77bcda00ad36157468befc712954b.gz commit ecc6f6e523cc478b960c3da2ca63252c178bd0e2 Author: Michael Olson <mwolson@gnu.org> Date: Thu Jul 27 18:35:00 2006 +0000 emms-info: If the file does not exist, don't update its info and file-mtime. This fixes an error. darcs-hash:20060727183504-1bfb2-9943ddf765b56f83479b08cdffefb0e63e6a20f2.gz commit 2a51c5acdf238d6c6de5811ab0b9bedc90f57db6 Author: forcer <forcer> Date: Thu Jul 27 14:13:00 2006 +0000 Makefile: Don't split info output darcs-hash:20060727141340-2189f-04dc7c9508430653ff03cde0b1f8e402eebe6812.gz commit d84b90a32fc453e90eb1d6b8d8b5f207c9843859 Author: Damien Elmes <emms@repose.cx> Date: Wed Jul 26 18:17:00 2006 +0000 browser: add some documentation related to singles and filters darcs-hash:20060726181758-4e3e3-ea11e892b1478cd818c7d774fd8957093a971511.gz commit 940d0784c8d5faed2ded6799bfc9dc6499106aba Author: Damien Elmes <emms@repose.cx> Date: Wed Jul 26 14:38:00 2006 +0000 browser: fix a few cover bugs darcs-hash:20060726143832-4e3e3-94f75a65138f9c49f0c94f348d437c93ca5158ef.gz commit 503bbce69bdbf6d7d3b54d14a1267886ede90f4d Author: Damien Elmes <emms@repose.cx> Date: Wed Jul 19 11:49:00 2006 +0000 add more lookup functions, a filter-changed hook, and fix an indent problem darcs-hash:20060719114958-4e3e3-a410266491ee984490b5d4b88cab813903847552.gz commit b089f2794908126bc7d75c6ae6634b993e8ee18d Author: yoni-r <yoni-r> Date: Mon Jul 10 22:04:00 2006 +0000 resolve bug reported by sebatian about the q key darcs-hash:20060710220453-85c19-e7f6d124b823015bd41a37c0a836ebedca86f8cc.gz commit c67578e60968de99fab41521e70a4b7002449980 Author: Damien Elmes <emms@repose.cx> Date: Mon Jul 10 18:24:00 2006 +0000 browser: fix keybindings darcs-hash:20060710182403-4e3e3-163401138844f8ef44c6d7a8920a932ac942a114.gz commit 868d5b3bca32f05f90d88c3698324ae6e7d0d3f3 Author: Damien Elmes <emms@repose.cx> Date: Mon Jul 10 18:04:00 2006 +0000 browser: add next/previous filter support darcs-hash:20060710180451-4e3e3-4b6b2a89bd865f0490b0f7c38b91ea9b383ca895.gz commit fb513e62baf6c8d7355be9aa4ebfa7ceab55ef61 Author: Damien Elmes <emms@repose.cx> Date: Mon Jul 10 17:23:00 2006 +0000 browser: improve filtering, update docs darcs-hash:20060710172313-4e3e3-4f59268d5701ca3e5e3d09accc562835ca5813a9.gz commit 3c03bb4d8a259cfd2612542b25c0e014b8ac0898 Author: Damien Elmes <emms@repose.cx> Date: Mon Jul 10 14:38:00 2006 +0000 mplayer: -playlist must be the last arg when streaming darcs-hash:20060710143807-4e3e3-7367953faf45a044690c602a7a9103015e95c734.gz commit 1e6871901a383ca0f5fc2be2fb723e60142f79e0 Author: Damien Elmes <emms@repose.cx> Date: Mon Jul 10 14:24:00 2006 +0000 mplayer: use really-quiet (might help on video files with lots of errors?) darcs-hash:20060710142405-4e3e3-6967760b29f2149f0ebea84147ffdc18936dd461.gz commit 9e567044cda73f04fdc894994843d778b3bcc8fe Author: Damien Elmes <emms@repose.cx> Date: Mon Jul 10 14:19:00 2006 +0000 mplayer: use quiet mode (stops skipping when emacs is busy) darcs-hash:20060710141939-4e3e3-77f600115c13362a6bda5a297750c707b61c72df.gz commit c05ccf0803530d8fddbcb58dc92daa3546469379 Author: Damien Elmes <emms@repose.cx> Date: Thu Jul 6 11:25:00 2006 +0000 browser: use generated name on top level enteries this fixes a bug where 'various' albums end up being classified under the first author of the first various album darcs-hash:20060706112523-4e3e3-b5fc3f33b7996292ce11ef38b111fd3df96e83f6.gz commit cf84eab8b93a5ce922b64bc13954166b9847c8bc Author: Damien Elmes <emms@repose.cx> Date: Thu Jul 6 09:51:00 2006 +0000 playlist: don't assume there's a track at point this makes RET on an group heading play the first track instead of failing darcs-hash:20060706095138-4e3e3-681dd364f708bcf5c88d0534d0019c091fb62707.gz commit 0bcea596a4ea9d5601259f34cab825d3bf1e8394 Author: Damien Elmes <emms@repose.cx> Date: Thu Jul 6 07:35:00 2006 +0000 browser: don't use text-mode-map as parent darcs-hash:20060706073532-4e3e3-2801f215411ab6469b4ac002a5d364ea498f3427.gz commit 1772f4f391923e955910bc35582361f0f8023ef8 Author: Damien Elmes <emms@repose.cx> Date: Thu Jul 6 07:31:00 2006 +0000 browser: add lookup of artist/album in wikipedia darcs-hash:20060706073102-4e3e3-0d7410b08c4748a26b252025090beeffb9f77791.gz commit d17aadfe7faa32710766b9d5f3b7a6e59361a2cd Author: Damien Elmes <emms@repose.cx> Date: Thu Jul 6 06:30:00 2006 +0000 browser: add filtering support (see comments at top) darcs-hash:20060706063045-4e3e3-abcefee16dc9272b7d76bc66869349d300cd597a.gz commit 49c0ec3cb47204b00601f66d7bdd3c6467d67b91 Author: Damien Elmes <emms@repose.cx> Date: Wed Jul 5 13:42:00 2006 +0000 browser: lvl is a bad name (fixes a bug) darcs-hash:20060705134200-4e3e3-acf9064722ab87de51766b92e7903f8f868b053b.gz commit a3bb0ffba1588416cb4f630c9d2f99b8864d401c Author: Damien Elmes <emms@repose.cx> Date: Wed Jul 5 13:34:00 2006 +0000 browser: don't rely on target to determine track properties Using 'track means that the format string symbols aren't generated properly. Note that these recent changes means that the browser and the playlist share the same face. It's not too hard to change this - what do you think? Should the browser and playlist track face be different? darcs-hash:20060705133450-4e3e3-0743a44a91f05f825f146eedf21163ff41d69db6.gz commit a6b5c7855486045daeff9db25e224896a2eb0f73 Author: Damien Elmes <emms@repose.cx> Date: Wed Jul 5 13:16:00 2006 +0000 browser: propertize playlist tracks in formatting code darcs-hash:20060705131640-4e3e3-30381f6ff30aecd8d7ccab57a2f7bf0e71b52696.gz commit 84ec279f7b4731899ef0ebf8d80483d88ce26f10 Author: Damien Elmes <emms@repose.cx> Date: Wed Jul 5 11:47:00 2006 +0000 browser: refactor level handling code - remove insert-track-function, it's not needed - playlist indentation is now handled the same way as the browser, using format strings - dynamically bind the relative level to make the above work - indent tracks a little more to make them visibly "under" albums darcs-hash:20060705114748-4e3e3-362beab720e68610925c927e0f4638f43f1fad1a.gz commit 303055e04a5556dc412e69189d6985b917555ed1 Author: Damien Elmes <emms@repose.cx> Date: Tue Jul 4 15:34:00 2006 +0000 browser: indent albums, don't propertize indent darcs-hash:20060704153422-4e3e3-ebb8cf0b25fc1599729c43675016956551388ea4.gz commit 6bc9791da7daebbc89bb6f2ad2da83c14a5f8ff8 Author: Damien Elmes <emms@repose.cx> Date: Tue Jul 4 14:01:00 2006 +0000 browser: make faces dependent on type, not level also renamed the faces - you'll need to customize them again if you've customized them before. darcs-hash:20060704140109-4e3e3-3e575fd46005c48cacc715f4f4fa5ec35249a2a9.gz commit c02d6cf3b3cadeea7e2063f96696cd2edb70468e Author: Damien Elmes <emms@repose.cx> Date: Tue Jul 4 13:14:00 2006 +0000 browser: set missing elements to 'misc' to prevent failure darcs-hash:20060704131400-4e3e3-2e9081e6826ba4fcbfcb450d77aa5e66cdd521a1.gz commit 7749a597540993c1fe49e086ff41623541658160 Author: Damien Elmes <emms@repose.cx> Date: Tue Jul 4 12:56:00 2006 +0000 browser: add no-cover documentation darcs-hash:20060704125634-4e3e3-f75ae479c99c8085119f4ce35698ad432ea635e4.gz commit 9826f396b020fd61abcb7a0fd16b1d074a53c429 Author: Damien Elmes <emms@repose.cx> Date: Tue Jul 4 04:43:00 2006 +0000 browser: don't need point-at-bol, code has been refactored darcs-hash:20060704044315-4e3e3-bd659adfefc1698b5c0486338d0046f0885e78c0.gz commit 05f1a90f4299b7c4ef307e48e29917c4c5acd66b Author: Damien Elmes <emms@repose.cx> Date: Tue Jul 4 04:40:00 2006 +0000 browser: add default covers, fix bug darcs-hash:20060704044020-4e3e3-d0f91c965a5820c1afaa14a4131fd780cc4aed11.gz commit 0ea391b453a8996d3fa17536159a5b8d6b96851b Author: Damien Elmes <emms@repose.cx> Date: Sun Jul 2 09:13:00 2006 +0000 browser: beginnings of format string support darcs-hash:20060702091318-4e3e3-43eece589404da9ff1ba8c9308960f14d881beb1.gz commit 481ae8b43447ccaf30d1adbce313dacb2956be62 Author: Damien Elmes <emms@repose.cx> Date: Sun Jul 2 03:03:00 2006 +0000 cache: set coding cookie in cache file darcs-hash:20060702030320-4e3e3-c05bba88a4c05550bef892d79cf581f716567d12.gz commit 62ff681882fdf81d2c9abd82d149063a9658eeb7 Author: Michael Olson <mwolson@gnu.org> Date: Sun Jul 2 03:37:00 2006 +0000 emms-browser: Use point-at-bol instead of line-beginning-position for XEmacs compatibility. darcs-hash:20060702033721-1bfb2-a594cdc0e93fceb6081b805fc511ef536df83c5a.gz commit afe2cacd997d7d3c680843339177ba4e1b82c652 Author: Michael Olson <mwolson@gnu.org> Date: Sun Jul 2 02:03:00 2006 +0000 Fix more XEmacs issues. darcs-hash:20060702020302-1bfb2-ce8e5060cf1f7db0cf52e40d711d16e621f3968c.gz commit 4a873b05b48e1b3bca23499494cff40bf6a3e74a Author: Michael Olson <mwolson@gnu.org> Date: Sun Jul 2 01:21:00 2006 +0000 Allow player to set the exact elapsed time of a track. emms-player-mpd and emms-player-mpg321-remote both need this. darcs-hash:20060702012131-1bfb2-3e6229d68adf0d78574e0fc6cd1c1a4438c870c3.gz commit accfde0f1a53e921406bb352fc5c3081ef9dbe97 Author: Michael Olson <mwolson@gnu.org> Date: Sun Jul 2 00:12:00 2006 +0000 Make emms-cache and emms-browser work with XEmacs. darcs-hash:20060702001247-1bfb2-987d207f3c007211aae68e8061a2a16fdc6960a7.gz commit 6dfa85c0487668269d9f08543483aa1d4f4258ff Author: lucas <lucas> Date: Fri Jun 30 22:08:00 2006 +0000 browser: bind 'C' to clear the playlist from the browser window. darcs-hash:20060630220804-4f952-d803c7f547027551362a1a8de638d4e3ccc4bb3e.gz commit 68bf7c8740c1c8371b71a613b57d00bc6a114f00 Author: Damien Elmes <emms@repose.cx> Date: Fri Jun 30 12:40:00 2006 +0000 browser: d for dired (missing half) darcs-hash:20060630124050-4e3e3-19caf3a3694a8e8cbba8d2a6cfc6ac60f08bc3ca.gz commit fe45a4a8a165cb7ce7e1604453408cce873c0e1b Author: Damien Elmes <emms@repose.cx> Date: Thu Jun 29 17:54:00 2006 +0000 browser: add 'd' to open dired on the current directory darcs-hash:20060629175424-4e3e3-1301f36cece1ae2f55616133c652baddf606c36c.gz commit 372698a16cdd87f0f95cabde3e6c9f0e5f227432 Author: Damien Elmes <emms@repose.cx> Date: Thu Jun 29 14:13:00 2006 +0000 browser: fix bug with custom cover fetching function darcs-hash:20060629141356-4e3e3-e469426ab411ae28b58dead6de6302c9528362ea.gz commit 7636b83b39c4d020b6324bebccc7b62965369d3b Author: Damien Elmes <emms@repose.cx> Date: Thu Jun 29 13:24:00 2006 +0000 browser: cover display, compilation support,more - added optional rendering of cover images in the browser and playlist (see http://repose.cx/dump/browser-images.png) - display artist name if browsing by album - add `emms-browser-get-track-field-function', which allows you to customise the way the browser sorts the cache into various albums, artists, etc. includes a function (not on by default) which finds the artist name by the directory, not tag info - this prevents making lots of top level artist entries for artists who only appear on a compilation darcs-hash:20060629132444-4e3e3-142af90538863a1f655494b24de89ef39ea2a4dc.gz commit 69abf5b78ac67197dfedc1f15c49eaaddbce297a Author: lucas <lucas> Date: Tue Jun 27 22:07:00 2006 +0000 emms-browser: add C-j as an alternative to C-RET for console users darcs-hash:20060627220759-4f952-eea5cba96a2a2313b267e6efbc8bbfad914ba502.gz commit 88f57b8804b6df32844770ece036075e1a1ac64d Author: yoni-r <yoni-r> Date: Mon Jun 26 16:04:00 2006 +0000 emms-playlist-mode-window-width defcustom + emms-playlist-mode-center-when-go darcs-hash:20060626160415-85c19-b96c96fccb4ef99f70e98f1e83e0a88e4113f41b.gz commit 50eebbbff0345d945ac7073273a034d8a3071e0b Author: yoni-r <yoni-r> Date: Mon Jun 26 14:15:00 2006 +0000 make M-> act like a normal Emacs buffer for emms-playlist-mode darcs-hash:20060626141534-85c19-d4133931635bd1f01bd5295567d2a4678d778ad4.gz commit 5e4ffd984d94f89699d038bfd8ff06154fb27dc7 Author: lucas <lucas> Date: Sun Jun 25 17:56:00 2006 +0000 emms-last-played: Count the number of times a track has been played. By default, EMMS will now store the number of times you play a track. darcs-hash:20060625175654-4f952-0143f8621918567caed0a6587da7a5d3bfea409c.gz commit d60c90d8def9ebee49d7cae0acc0010b3abad8c8 Author: lucas <lucas> Date: Sun Jun 25 16:20:00 2006 +0000 emms-cache.el: fix missing paren in emms-cache-sync darcs-hash:20060625162044-4f952-a5c2c56dc79f3b359ef298aef12ec3a9c1d3ed57.gz commit e3a70f91583e7ced9e6d2fa9c1a8e9e2521dc7fa Author: lucas <lucas> Date: Sun Jun 25 11:33:00 2006 +0000 emms-browser.el: fix bad keybinding for emms-browser-goto-random darcs-hash:20060625113348-4f952-20e508ab3d73b040f6c92f8b9208110c1a9c621e.gz commit 8f9c1dcdff81825ce5af9f84359b70061769f284 Author: Damien Elmes <emms@repose.cx> Date: Sun Jun 25 11:01:00 2006 +0000 cache: readability fix darcs-hash:20060625110138-4e3e3-796352e4a7992026d4d073755b8d9c7aa53b26fc.gz commit bd115b86296fa6f88b7f945a308cbb89027c68b3 Author: Damien Elmes <emms@repose.cx> Date: Sun Jun 25 10:51:00 2006 +0000 cache: rename function, remove obsolete one, only mark dirty if necessary darcs-hash:20060625105130-4e3e3-9eeb2d394b4324c8cefcfd9aae0a9b8a40971258.gz commit 507729e70357d5e9d55c0276907e04fc22223289 Author: lucas <lucas> Date: Sun Jun 25 09:59:00 2006 +0000 emms-cache.el: Move the pruning code inside emms-cache-refresh. darcs-hash:20060625095901-4f952-96d60b326e8e09587e2d92cffc838f00864241a4.gz commit 3672c9ee39f0d15815a79e69dc1a52a9cfbb8b44 Author: lucas <lucas> Date: Sun Jun 25 11:24:00 2006 +0000 emms-browser.el: emms-browser-goto-random moves the point to a random line in the browser. darcs-hash:20060625112441-4f952-c9517489eb33dd2865a3d8f6fbdf922b3a989acb.gz commit 6dc53f98e6c2acce8852ce71f58164bb0603733e Author: Damien Elmes <emms@repose.cx> Date: Fri Jun 23 17:12:00 2006 +0000 browser: another read-only bug darcs-hash:20060623171252-4e3e3-2270fbde08d8e29914b9ee2614bcf70d2c4bcf5a.gz commit ce36e03ee5fe51ad8dc4ef0b4f15f6036624230b Author: Damien Elmes <emms@repose.cx> Date: Fri Jun 23 15:09:00 2006 +0000 browser: fix bug with read-only buffer darcs-hash:20060623150933-4e3e3-7a835c979f1f6283d0aeda7c4cbc55653f2a3e74.gz commit 43d2e4e473c8561dc7ad54813bb5aad82981face Author: Damien Elmes <emms@repose.cx> Date: Fri Jun 23 15:04:00 2006 +0000 browser: more search stuff - fix bug where we clobber emms-browser-buffer - clear search on new search - add new keybindings - 's a', 's s', etc. to search for different fields. darcs-hash:20060623150406-4e3e3-9096e56597ae119fdee324255894b2858cef702f.gz commit 32aa5c2203d7f63bf88c6853f2e2f42788eb3890 Author: Damien Elmes <emms@repose.cx> Date: Fri Jun 23 14:28:00 2006 +0000 browser: preliminary browsing support darcs-hash:20060623142837-4e3e3-7397b81dc867876785cf43357bf18c8973e6b010.gz commit 4a174ab71e24c4459fdd015194041bf05f4b1ea1 Author: yoni-r <yoni-r> Date: Thu Jun 22 20:46:00 2006 +0000 function name change + testing emms-patches mailing-list darcs-hash:20060622204637-85c19-cd8bc0fdb4fdad6279d9996c0820de139e13dc27.gz commit 4b201371ac9d96070c13bfd8da9bebeb5dc5df10 Author: lucas <lucas> Date: Thu Jun 22 23:17:00 2006 +0000 README: added a note about compiling emms-print-metadata, since it apparently wasn't obvious... darcs-hash:20060622231759-4f952-2d232e9530b6990ea41ba6d8b8d78d0e4b717c87.gz commit 963010890b497f9eabfb2738ee50734a1befa539 Author: Damien Elmes <emms@repose.cx> Date: Thu Jun 22 11:27:00 2006 +0000 browser: use the filename if no useful metadata is available darcs-hash:20060622112720-4e3e3-7067174f9a1f6013bbfecb73e8effc03fdce5d52.gz commit 859fe8dd6b7d0a525fc15d31a84844ff36da1cb6 Author: Damien Elmes <emms@repose.cx> Date: Thu Jun 22 11:14:00 2006 +0000 browser: uniquify track names, mpg321-remote: restart dead process darcs-hash:20060622111421-4e3e3-d843dafdb0245f9e08c032ad43bed6b2dc10c701.gz commit a3a19b09ccbb3b9909d3ce50a21b8fe3ca2636b8 Author: Damien Elmes <emms@repose.cx> Date: Thu Jun 22 11:45:00 2006 +0000 cache: add a routine to refresh metadata info darcs-hash:20060622114528-4e3e3-edaed29b327826bdbac2e172177dfa9e37214c15.gz commit 6115f3d510a1d052921210268575ec54a358523c Author: Damien Elmes <emms@repose.cx> Date: Tue Jun 20 09:19:00 2006 +0000 README: fix a small typo darcs-hash:20060620091959-4e3e3-9eb13a61aefbe79769a4c61c96f2ba6cf40a21aa.gz commit 544e06a3b7a1f759317e984b87464632a7548eda Author: lucas <lucas> Date: Tue Jun 20 06:52:00 2006 +0000 README : Advanced configuration : added item about seeking. darcs-hash:20060620065241-4f952-57b870e39b27d3377015ebf0e9deb49c9c43412d.gz commit c487efd4d968a1859e7e6d446ad3834c2ec1dd1e Author: william.xwl <william.xwl> Date: Sun Jun 18 12:03:00 2006 +0000 emms-player-mplayer.el: Enable mplayer's slave mode for seek support by default. darcs-hash:20060618120337-e8fe6-c9425c08e3d4cca0801c8e1551aa455d88549a7d.gz commit e70aa542abad8aa8493c803b0fe52e7631a398e3 Author: william.xwl <william.xwl> Date: Sun Jun 18 12:02:00 2006 +0000 AUTHORS: Update William's info. darcs-hash:20060618120236-e8fe6-308f405fc475583ee88fc6d1418700bd6edf7a61.gz commit 8b5e7ce79e8b3f79d9c351ae756cac9be4fdf81a Author: Damien Elmes <emms@repose.cx> Date: Sun Jun 18 12:25:00 2006 +0000 browser: bugfixes, sort/display by year - fix a bug with add-and-play on a single file - display album year if available - sort albums first by year - add c-1, c-2 etc keybindings to quickly browse by artist, album, etc. (conflicts with standard keybindings - assumption is that digit-argument is probably not very useful in the browser mode) darcs-hash:20060618122507-4e3e3-d961861072a8a07e2f67b391c6f59b7ea1a79ac9.gz commit f5c591cdd5ca4351f7ec5070206ba237506e8638 Author: forcer <forcer> Date: Sat Jun 17 02:35:00 2006 +0000 define-emms-simple-player: Check for existence of the player executable. darcs-hash:20060617023535-2189f-d285035e40953c1c8512d823c1332266294a5f4e.gz commit 5fa90c9bbe89551ad6b62a008709f2359e754ae0 Author: william.xwl <william.xwl> Date: Fri Jun 16 16:22:00 2006 +0000 Rename `emms-score-show' to `emms-score-show-playing'. Add `emms-score-show-file-on-line'. darcs-hash:20060616162244-e8fe6-91e510b1ef2d25f1245edfb5f635657bd2227921.gz commit 4af11977682dd18f07484de299f0ab11b07032e0 Author: Michael Olson <mwolson@gnu.org> Date: Fri Jun 16 23:38:00 2006 +0000 emms-player-mpd: Make the playable-p function return nil if we cannot start a connection to mpd. darcs-hash:20060616233847-1bfb2-6b95e1e17b907cc46204c74b7ea9a59963e86dde.gz commit 5f68d4a7e7d38db5d53b3d5cbfc4d363377c91e1 Author: Damien Elmes <emms@repose.cx> Date: Fri Jun 16 15:32:00 2006 +0000 browser: put track number first (better for compilation albums) darcs-hash:20060616153258-4e3e3-6ac627d571ef0623a346b8806c099f0d2c786ee5.gz commit 22095d1a142dade2382cd811849e4502d975b716 Author: Damien Elmes <emms@repose.cx> Date: Fri Jun 16 13:27:00 2006 +0000 browser: fix centering when adding new tracks to the playlist darcs-hash:20060616132746-4e3e3-177ab8c37d4b5041d47ddbc6f1a42c30413f99aa.gz commit 73810bc2e36ee74b2dae29bbbde5f1fd9c99d970 Author: Damien Elmes <emms@repose.cx> Date: Fri Jun 16 13:19:00 2006 +0000 browser: remember position when hitting 1,2,3 etc darcs-hash:20060616131926-4e3e3-48d11c2d5b27bd26c8ed5ccf4e96f2c0480cf1da.gz commit 6ce6dd88e208a36baa641ec5c5c06b849353b944 Author: Damien Elmes <emms@repose.cx> Date: Fri Jun 16 11:06:00 2006 +0000 browser: collapse before expanding (expand-to-level-2, etc) darcs-hash:20060616110612-4e3e3-4c3668a61018c2478c42a1ceeeaa38e19e1cc292.gz commit 81ada156e698dd8f748a93ac0161f7899ca844fe Author: Damien Elmes <emms@repose.cx> Date: Fri Jun 16 11:02:00 2006 +0000 browser: fix sorting on tracks without a track number darcs-hash:20060616110222-4e3e3-616f148328a86000b55e03b878436a77b62013d4.gz commit 5d67351b36d4050677e3d5cba35c298c18690bc0 Author: Damien Elmes <emms@repose.cx> Date: Fri Jun 16 10:31:00 2006 +0000 mpg321-remote: fix race condition darcs-hash:20060616103159-4e3e3-fd8d7c3ce8e35b26f56f4822e65b7a217eaf4436.gz commit eefcda079f253ed0e154254766a8e0407e318000 Author: Damien Elmes <emms@repose.cx> Date: Fri Jun 16 01:13:00 2006 +0000 mpg321-remote: fix bug related to the player stopping darcs-hash:20060616011318-4e3e3-47d8fbfd25b67617a99f9116af74373ca69d63c1.gz commit caf5a848fa073551e5ff033cda23c9268c727dc4 Author: forcer <forcer> Date: Thu Jun 15 22:57:00 2006 +0000 Add Adam Sjoegren (copyright got assigned) darcs-hash:20060615225714-2189f-b228de0c9c275cd11b7abbdeb2aec2fe5cd3d0df.gz commit 94e55c7215448cd85ba606c2c6fc20f9ff60d637 Author: Damien Elmes <emms@repose.cx> Date: Thu Jun 15 09:42:00 2006 +0000 mpg321-remote: defvar mask-stop-message darcs-hash:20060615094217-4e3e3-258d67013b40b8be7cd3da95ed77ea740407df28.gz commit 395d69cb965b6905b7b87b6f8ae062dfe3423c56 Author: Damien Elmes <emms@repose.cx> Date: Thu Jun 15 06:30:00 2006 +0000 add player-mpg321-remote - allows seeking in files - handles files with errors in them (the mpg321 simple version skips over the files) darcs-hash:20060615063027-4e3e3-55f9b446189c86894879167259604cda28fe5215.gz commit a835d3cdafbe77f6170ee148d0a4ca9c977bbd05 Author: Damien Elmes <emms@repose.cx> Date: Thu Jun 15 05:11:00 2006 +0000 browser: fix for the tracknumber fix patch darcs-hash:20060615051156-4e3e3-9bedf86523e556a6b5017909df3969a63cf7ffaf.gz commit 181d7555612d78edaa78693fc10a9483731e4549 Author: Damien Elmes <emms@repose.cx> Date: Thu Jun 15 02:36:00 2006 +0000 browser: handle nil track numbers darcs-hash:20060615023650-4e3e3-1339418ceb7187db50d61db622d7f3d69420dd8e.gz commit 755ea4ee927779f9c7912d74b94e821c4ee1a3ee Author: Damien Elmes <emms@repose.cx> Date: Thu Jun 15 02:28:00 2006 +0000 playlist: enable undo, add extra undo binding darcs-hash:20060615022826-4e3e3-249a0a736f1fc3d97d8536c0281a3323e06b3b15.gz commit 8c7dbf401ccdbfcf4b5033d1168d5dd8b15686ef Author: Damien Elmes <emms@repose.cx> Date: Thu Jun 15 01:55:00 2006 +0000 browser: require emms-playlist-sort darcs-hash:20060615015543-4e3e3-880815ff2d361e255818d721449d98707827cdbb.gz commit 4c6f8243bb54321fb9d244743cc736c958762a5a Author: Damien Elmes <emms@repose.cx> Date: Thu Jun 15 01:34:00 2006 +0000 playlist-mode: add 'C' to clear playlist darcs-hash:20060615013417-4e3e3-ce0b3c0cebb6c4535cb58755d016f717e18a9a22.gz commit 88d8dbedbab92ec5694f8f39da12e612dc72cb49 Author: Damien Elmes <emms@repose.cx> Date: Thu Jun 15 01:28:00 2006 +0000 info: display progress when adding async darcs-hash:20060615012854-4e3e3-746ce41e3529fa7177bbe9a516b24bb3b451c229.gz commit fa12a8d188103712777c3b8e1c3787a913809167 Author: Damien Elmes <emms@repose.cx> Date: Thu Jun 15 01:36:00 2006 +0000 browser: make defcustom lines user variables darcs-hash:20060615013606-4e3e3-97fd6bb688b5ca726badc3ad75e1c3d931dd0dad.gz commit 2659d7aa49efdf5ab4063dce10f3cd6e25969001 Author: Damien Elmes <emms@repose.cx> Date: Wed Jun 14 18:07:00 2006 +0000 browser: expand/collapse levels, tab through entries darcs-hash:20060614180725-4e3e3-948380dee9f4b29be1ef14cedcd463a9222bb935.gz commit c6dbd8f17dac67fc95d4bfa6ef796073a38ff263 Author: Damien Elmes <emms@repose.cx> Date: Wed Jun 14 16:00:00 2006 +0000 browser: refactor data format, bugfixes; emms: add emms-track-p Subitems are now stored in a tree of "bdata" objects, which is generated when initially displaying the buffer. This makes rendering simpler and also fixes some bugs where tracks were not being sorted correctly in the browser and/or the playlist. Adding items to the playlist now inserts 'group' names when you add a whole album, artist, etc at a time. These names will be thrown away if you run emms-shuffle. The sorting routines will correctly sort the buffer, throwing away the group tags, but then throw an error because the buffer is not the size they expected it to be. Other playlist manipulation routines like next/previous should skip over the group names - if they don't, it's a bug in the playlist code. An example of the new interface is at: http://repose.cx/dump/emms-browser.png darcs-hash:20060614160048-4e3e3-82a8a0d1678b0a2d9fcfc6ca385d5b56963aedbe.gz commit 3f741b53e67b30d556a894f5f19adc35a16a2085 Author: william.xwl <william.xwl> Date: Wed Jun 14 03:21:00 2006 +0000 emms-lyrics.el: Fix file-exists-p error when finding lyrics file for streams. At present, will just take care of tracks with 'file type. darcs-hash:20060614032114-e8fe6-52bf61bc4fbdfe3d4b212123c84514bc0e15697e.gz commit 39b42febb1f1c5fe75547271cad33eb29e9fde72 Author: yoni-r <yoni-r> Date: Tue Jun 13 10:01:00 2006 +0000 added the section "Finding files and speed" to the manual darcs-hash:20060613100136-85c19-5c278ce45fa496e37f3d4ba1f5c15e7bb08c1c9a.gz commit 4cf3a346444fc11195dc609db892ecdea17cda7a Author: yoni-r <yoni-r> Date: Tue Jun 13 09:06:00 2006 +0000 fix bug in emms-playlist-mode-center-current darcs-hash:20060613090604-85c19-189240fc999924c5bd441319f2de9afc1bb49b6f.gz commit 57ce5391b5d471a4ada74b322b0904a0809a0639 Author: yoni-r <yoni-r> Date: Sun Jun 11 18:54:00 2006 +0000 removed superfluous comment (actually testing darcs send) darcs-hash:20060611185407-7e588-4b79a6030aa9519b6ae7b3b79c3747fb2031f4ec.gz commit 82c841900412d8d8bfc6cb87fa6cf831ab8bc19f Author: forcer <forcer> Date: Mon Jun 12 19:16:00 2006 +0000 debian: add changelog for 2.0-2 darcs-hash:20060612191609-2189f-44a3d90b48e46988585c90cada9e34e7146c734c.gz commit 3554f4090ab90f5fd318faf2c2e62e0495f22061 Author: forcer <forcer> Date: Mon Jun 12 19:12:00 2006 +0000 debian: Install info file as well darcs-hash:20060612191255-2189f-381f44ecd8f1a484de86ab702324b83cd785a342.gz commit 07325b244eb5fc5fbd802ff946cbff6e5ac49a8b Author: Damien Elmes <emms@repose.cx> Date: Mon Jun 12 05:18:00 2006 +0000 browser: sorting, bugfixes - add sorting for subitems (albums, tracks, etc) - make isearching expand the current entry automatically - rename subitems-exist to subitems-visible (clearer) darcs-hash:20060612051800-4e3e3-a6e9e2c341ab3caf5f5aa59c364ae3bb2362ac3e.gz commit ee459cbdc7b0fe86ea5815bfcc0633a6f471a617 Author: yoni-r <yoni-r> Date: Sun Jun 11 16:39:00 2006 +0000 updated manual about emms-foobar-file prefix toggling darcs-hash:20060611163901-6ce53-462fe67b2b620ef13edb95b0b87a37df0b0b0f6b.gz commit 0d8660d516e90069b6442b9a68072a2346d15d63 Author: Damien Elmes <emms@repose.cx> Date: Sun Jun 11 09:54:00 2006 +0000 emms-cache: add pruning support, make save/load interactive darcs-hash:20060611095400-4e3e3-5624cdc454d14b7f4ffb03cc84f8883bf2fe291e.gz commit 0b2e933c5c46532b2e94cf4542571d2bdfd16862 Author: Michael Olson <mwolson@gnu.org> Date: Sat Jun 10 23:05:00 2006 +0000 Use better exclude regexp, so that people can load music files with '#' in the middle of the name. darcs-hash:20060610230507-1bfb2-b43f8403de4b1123ef7a71408f86510b7a553e63.gz commit 3540a17fdd5792376cdb78695280a15ee189eec5 Author: Michael Olson <mwolson@gnu.org> Date: Sat Jun 10 23:04:00 2006 +0000 emms-info: Never return 0 for info-mtime, since emms-time-less-p does not like this. Use nil instead. darcs-hash:20060610230409-1bfb2-fa73c67de417d1643dfb3b99cd7cf16b861ff8ab.gz commit f07ea4645d724d38c68a3f03d00439d9f7d1f96e Author: Martin Schoenmakers <aiviru@diamond-age.net> Date: Fri Jun 9 23:11:00 2006 +0000 Add mpd volume settings to custom Small patchlet so mpd users can use custom to change the volume setting backend to use the appropriate volume functions. darcs-hash:20060609231150-97144-06f60160ea3afb3de4a43dcd861601c03a8a6dc2.gz commit 95ef705e702814617555f1e663ed8a969e398c8b Author: Damien Elmes <emms@repose.cx> Date: Fri Jun 9 18:59:00 2006 +0000 browse subcategories (eg artist->album->title) - subcategories can now be expanded and contracted, and added to playlist - see the new keybindings at the top of the file - add new faces for the various sublevels (only the dark background colours are useful at the moment - any light background users want to fix that?) - fix a bug in emms-smart-browse with (recenter) darcs-hash:20060609185950-4e3e3-70f66178dae24374b5023d6f76ec08bea779d1e1.gz commit 6a717855498454bda736bda881cc203c0978b1fd Author: Damien Elmes <emms@repose.cx> Date: Fri Jun 9 06:49:00 2006 +0000 update emms-cache.el commentary darcs-hash:20060609064935-4e3e3-cd3861e10f6aad3d118c6c87cd87438d6f5bc892.gz commit ce12375555588a7ad969bcb0e26a38220012f930 Author: Michael Olson <mwolson@gnu.org> Date: Fri Jun 9 04:38:00 2006 +0000 emms-player-mpd: Add functionality to dump MusicPD data into the EMMS cache. This allows for easy integration with emms-browser.el. darcs-hash:20060609043831-1bfb2-7c886a447a80ecd694c053d2a8a1a18f807e4594.gz commit 0d9aba2a5168b500a7b9073730d00113411d2f16 Author: Michael Olson <mwolson@gnu.org> Date: Fri Jun 9 04:36:00 2006 +0000 emms-player-mpd: Rename volume functions to better match the namespace created by emms-volume.el. darcs-hash:20060609043643-1bfb2-375117b7d9fef9f60119cb64b42095c609448a30.gz commit 4a809e2083f80a70db9a8d128e194ff976baa08c Author: Michael Olson <mwolson@gnu.org> Date: Fri Jun 9 04:35:00 2006 +0000 emms-player-mpd: Fix minor bug when importing the current MusicPD playlist into EMMS. darcs-hash:20060609043538-1bfb2-40772d8300e40cdd9d4af794e6e8d3078e4f35f9.gz commit 4bc8afdebbf0a8481688f7d4d58b758a74390b12 Author: Michael Olson <mwolson@gnu.org> Date: Fri Jun 9 04:20:00 2006 +0000 emms-setup: Get rid of pointless compiler warning. darcs-hash:20060609042002-1bfb2-16505ccb1e785f16743bda984768c03d07eb7a74.gz commit 2d20eeafa0471f5a8dae57285d75716291b3b71b Author: Michael Olson <mwolson@gnu.org> Date: Fri Jun 9 04:16:00 2006 +0000 emms-cache: Small compiler fix. darcs-hash:20060609041606-1bfb2-6ea5623f62d4ff27566ab9f1097d5c4ffa2d95cb.gz commit 0f73de32500bb2cfe99d9fa7fbd730addd67d46a Author: Michael Olson <mwolson@gnu.org> Date: Fri Jun 9 04:01:00 2006 +0000 emms-cache: Add standard enable/disable/toggle interface and do a docfix for emms-cache-set-function. darcs-hash:20060609040108-1bfb2-268d7a1f4c7590ffdedcda9506bfca53e02cc2ea.gz commit ad3d6bb6d898cc42f673b99ea3721357d62c7d8f Author: Michael Olson <mwolson@gnu.org> Date: Thu Jun 8 19:41:00 2006 +0000 Standardize copyright notices. Add COPYING file. Mention license in README. darcs-hash:20060608194123-1bfb2-cbfbc9eacb41016b24acb9ea2654f141496b0caa.gz commit ececf6862bde0815211e5596c7a8cf76304b11f5 Author: Michael Olson <mwolson@gnu.org> Date: Thu Jun 8 18:46:00 2006 +0000 Fix compiler warnings in emms-cache.el. darcs-hash:20060608184612-1bfb2-942ae7db648d88b9dfe4896872fc3f5fdd7a30d3.gz commit 5e88f995fec0d274da36801cb97052959b928bcd Author: Michael Olson <mwolson@gnu.org> Date: Thu Jun 8 14:38:00 2006 +0000 emms-metaplaylist-mode: Fix bug introduced by the recent emms-playlist-mode overhaul. Add faces for light backgrounds. darcs-hash:20060608143846-1bfb2-e25dbaa46a3651f1acfd1aefc88f9ad32f03c365.gz commit e02148c940c8adf239e8c1510e9ddc172367716e Author: forcer <forcer> Date: Thu Jun 8 12:55:00 2006 +0000 NEWS is new darcs-hash:20060608125507-2189f-f04e5ed39a7888f4b6acbbd00f01754976b71286.gz commit 4c261ddd3b89b61217ea52ad26ff258956cf8c79 Author: Damien Elmes <emms@repose.cx> Date: Thu Jun 8 12:36:00 2006 +0000 refactor browser mode creation code - make the rendering function (browse-by-artist, etc) responsible for the mode name - fix a bug where the wrong buffer is used darcs-hash:20060608123618-4e3e3-b5bd1de42108ed792b6aa17cf9042dd22137b605.gz commit 01ba6d4850111dcc92d259ccaaff072458d40263 Author: Damien Elmes <emms@repose.cx> Date: Thu Jun 8 10:52:00 2006 +0000 browser sorting, and bug fixes - sort tracks when they're added to the playlist - fix a bug where we didn't uniquify the buffer - distinguish between files and urls - modify emms-playlist-sort to accept an optional region darcs-hash:20060608105253-4e3e3-d735756c02bcae5a7c2e8a9b97817cf393a58079.gz commit fdd132b103b3b62e51d0bda64eb60d4c3d9fcfa1 Author: Damien Elmes <emms@repose.cx> Date: Thu Jun 8 09:40:00 2006 +0000 update modeline when changing browsing method darcs-hash:20060608094037-4e3e3-941aa4374482cf0cbac1c4ea09f4aad83704a6e3.gz commit 3c8a654f4c67af7c44581828fb3a9e89400aae62 Author: Damien Elmes <emms@repose.cx> Date: Thu Jun 8 09:26:00 2006 +0000 avoid rebuilding the browser window each time darcs-hash:20060608092623-4e3e3-34036792deb3f6cc1c2ec4f97c5f81cf9f83291c.gz commit 10590679f8cdeb573981e79455fd99dfdf40f54f Author: Damien Elmes <emms@repose.cx> Date: Thu Jun 8 03:25:00 2006 +0000 small typo fix darcs-hash:20060608032546-4e3e3-8c445e10d32239209759b42957335a54e1d7390e.gz commit 0ac8fee949bfd85e4d7c1d3213297ab6dfeae7be Author: Damien Elmes <emms@repose.cx> Date: Thu Jun 8 09:07:00 2006 +0000 fix RET on trailing \n \n isn't propertized which means hitting RET on a playlist or browser entry fails. this patch moves the point before trying to read the properties. darcs-hash:20060608090703-4e3e3-56f8e91f35d92f217517222b1f1e3206f83b1825.gz commit 4ccf4e44c94e4b7471ee0aee968a05a9a0720982 Author: Damien Elmes <emms@repose.cx> Date: Thu Jun 8 08:44:00 2006 +0000 add a metadata browser - emms-browser.el * preliminary work on a metadata browser - still alpha, but it's useable for me * also updated my email address in emms-cache.el (whoops) darcs-hash:20060608084400-4e3e3-f9350d06fb1dabc33c33c9821a7d89c287c64a81.gz commit ef8524bc4ec77359010613ab0f198c1a9b1b886e Author: forcer <forcer> Date: Thu Jun 8 12:30:00 2006 +0000 emms-playlist-mode: Facify tracks on startup. darcs-hash:20060608123052-2189f-197516bb8da9a1051f3e0ddac5f3bdd99fefcc89.gz commit d39f230120b6571bba29c75bd882404cfe6edc47 Author: forcer <forcer> Date: Thu Jun 8 02:56:00 2006 +0000 emms.el: Change directory to / before starting the player. darcs-hash:20060608025659-2189f-cf54016de0748a3d9dc3f706db32c3125229bc08.gz commit 162ccacf2da18280abc4c182b99c0151097ef2b3 Author: Michael Olson <mwolson@gnu.org> Date: Wed Jun 7 21:52:00 2006 +0000 emms-playlist-mode: When making new overlays, do not allow the rear to advance. This prevents some display issues. If we really need to modify the text there, we should be using (insert-before-markers). darcs-hash:20060607215212-1bfb2-f306058603a47453dffe2182b8730cc3d9aaf5d9.gz commit db63cada789bce562c80d9db3a941deb32cb4ef0 Author: Michael Olson <mwolson@gnu.org> Date: Wed Jun 7 21:51:00 2006 +0000 Make emms-property-region bulletproof. darcs-hash:20060607215113-1bfb2-1d5710b9112fb1ed36d1a65d4ed432d643bdd863.gz commit 1fc051476607215c26a353e80b1f45b564415a4f Author: forcer <forcer> Date: Wed Jun 7 20:35:00 2006 +0000 Fix typo in emms-property-region darcs-hash:20060607203558-2189f-f2a8e6a89f4af46883dc23d656157bccd883db30.gz commit f9212a8941c84f9b1fe0056f0901b7e847367564 Author: forcer <forcer> Date: Wed Jun 7 20:23:00 2006 +0000 emms.el, simplified emms-property-region considerably. darcs-hash:20060607202310-2189f-16435d8796c61ef090f2215117e8042a482fde2b.gz commit 96a3ac588fbbd593558a305d95039abe8474a63c Author: lucas <lucas> Date: Wed Jun 7 17:28:00 2006 +0000 Very basic support for recording the time you last played a track. * emms-last-played.el: New file. Nothing fancy right now, more to come soon. * emms-setup.el: emms-devel now requires and setups emms-last-played. darcs-hash:20060607172830-4f952-fd247551c7da305be27b8f783e785bdd9c2c8689.gz commit 84acadce0e7916d1dd95a80aa69e57752ec80615 Author: forcer <forcer> Date: Wed Jun 7 16:10:00 2006 +0000 Mark the cache as dirty for each modification. darcs-hash:20060607161049-2189f-293b55878f4a073640a397e4b2aa563c3bf785d6.gz commit 06f6648e9a58761edfd5345f04e5ba8bb298bc48 Author: Damien Elmes <emms@repose.cx> Date: Wed Jun 7 15:40:00 2006 +0000 fix damien elmes's email address darcs-hash:20060607154000-4e3e3-41b5746bd18f69a30c288a7f86af3b49231ea0a8.gz commit 0af69e62ec87c6e83b6f45e3b0d0981247152358 Author: forcer <forcer> Date: Wed Jun 7 15:57:00 2006 +0000 emms.el: The currently playing marker now should stay where it is, even for yanks darcs-hash:20060607155759-2189f-f540a9d5692c72e253500b0580b42c5fad981ba5.gz commit e13420235286f2e17c8ec0a08a41a60959f14a3e Author: forcer <forcer> Date: Wed Jun 7 15:55:00 2006 +0000 emms-playlist-mode: Stop overlay from being attached to text inserted before it darcs-hash:20060607155511-2189f-8b77f04252183c1eb3c3f98737a33769afa01c99.gz commit 37853487955cb1eb28220448e48d96f9125c3685 Author: forcer <forcer> Date: Wed Jun 7 15:05:00 2006 +0000 emms sources now switch add/play behavior when a prefix argument is supplied. darcs-hash:20060607150502-2189f-111d096517e1b849d49e7f196852e51937a31b58.gz commit 7adf8d8e0913179aeedd93d8947f664456e94947 Author: forcer <forcer> Date: Wed Jun 7 15:00:00 2006 +0000 Add autoloads to emms-setup.el darcs-hash:20060607150030-2189f-66fac4c8280c702d0760683ce5079332c4a6d888.gz commit 36740ba4867876568390f5c83e603ce80869daff Author: forcer <forcer> Date: Wed Jun 7 13:46:00 2006 +0000 Typo, defvar => defcustom for emms-cache-set-function darcs-hash:20060607134647-2189f-af24ce177889add0924b39268a1924d36f3c8f82.gz commit f6694b874ce8cfa5651eceffbdbd0076bda44b7e Author: forcer <forcer> Date: Wed Jun 7 13:42:00 2006 +0000 Cleaned up the cached code in emms.el a bit darcs-hash:20060607134238-2189f-208cd31323c69521084137e367d689cead44a6df.gz commit e5beab412bc06197c77b902c4939758b2a246684 Author: Damien Elmes <emms@repose.cx> Date: Wed Jun 7 12:53:00 2006 +0000 refactor caching code into emms-cache.el * caching support is now provided via two function vars in emms.el, emms-cache-get-function and emms-cache-set-function * (emms-standard) or above will enable caching support * you'll need to remove .emms-cache or s/emms-info-cache/emms-cache-db/ darcs-hash:20060607125345-4e3e3-7d9ad8d243a395f2f2a5eea004e58ac9e239855b.gz commit 3f3081318870f5400f339e138e0115381451575a Author: forcer <forcer> Date: Tue Jun 6 14:15:00 2006 +0000 emms-playlist-mode doesn't need overlay compatibility anymore darcs-hash:20060606141539-2189f-9afa51a0ee2b36f7b083d01537cdc05f08d24670.gz commit 6ab9141298b6c620983d6c70b33ae6e02fe3099e Author: forcer <forcer> Date: Tue Jun 6 13:59:00 2006 +0000 emms-playlist-mode.el - now with less overlay! darcs-hash:20060606135908-2189f-bb652e384264445ca77b87e82bb0e190caf0f89f.gz commit afc461ef8513d1d5573cb5f71034203cb377cc1a Author: Michael Olson <mwolson@gnu.org> Date: Tue Jun 6 14:44:00 2006 +0000 emms-info: Fix bug that occurs after clearing the current playlist and trying to re-add songs to it. darcs-hash:20060606144439-1bfb2-34f362137ee2006e12ebfe26e7f3842c31f5ef0d.gz commit 239ad706c23e7ffc88914a8650a2f87bfc3944d5 Author: lucas <lucas> Date: Tue Jun 6 09:09:00 2006 +0000 AUTHORS: fixed Lucas' e-mail address darcs-hash:20060606090957-4f952-fa5341ba7b6e364b1619f0011ddfd1b5c85dfbbd.gz commit 7e45986db1b541e9e3c34394d856ee3780ad51bd Author: Damien Elmes <emms@repose.cx> Date: Mon Jun 5 16:33:00 2006 +0000 info-cache-dirty/coding * mark the info cache as dirty when it's modified, so we don't have to write it out all the time * save the cache as mule-utf-8 - comments? i'm not sure if this is correct darcs-hash:20060605163339-4e3e3-35731daf2d74d73bb6f776ad29de3f4cbe5d3529.gz commit a053a4d8c7f7bf39728c15647e1e558ccee9f3d6 Author: forcer <forcer> Date: Mon Jun 5 14:30:00 2006 +0000 AUTHORS: Damien Elmes address updated darcs-hash:20060605143028-2189f-e573f54db9aeba6cb82c3d6981c247a82d5f8aa5.gz commit 8ea1c649cb7cd734005e80da96026c157cd03f2f Author: forcer <forcer> Date: Mon Jun 5 14:25:00 2006 +0000 emms-info caching (thanks to Damien Elmes) darcs-hash:20060605142507-2189f-0edb660bd94f7d505bb6da6abc48cd595982bc31.gz commit 289268618b6a6edd6b5183fb363b15b3124854a9 Author: forcer <forcer> Date: Mon Jun 5 05:33:00 2006 +0000 Sort file names from `emms-source-file-directory-tree-function'. darcs-hash:20060605053347-2189f-e2161a5d791596968f9d9e83c004451592324550.gz commit c275727ea01b65c94c253e8649b7035d37bf67e1 Author: Michael Olson <mwolson@gnu.org> Date: Sun Jun 4 19:56:00 2006 +0000 Add some sources for inserting playlists without inserting their contents, and likewise for directories of playlist files. Exclude some files and directories from being added when walking directories. darcs-hash:20060604195602-1bfb2-3ebc047e47ecdece3b4b826b3a6a48ccbbb0f0d0.gz commit 9d10b8d562b427db7720433bc09ccdd6536dfc05 Author: Michael Olson <mwolson@gnu.org> Date: Sun Jun 4 19:54:00 2006 +0000 emms-player-mpd: Differentiate between files and URLs when it makes sense to do so. darcs-hash:20060604195449-1bfb2-5f43698ad0ff4945541f3aaf8244e1590333f39d.gz commit 4247641fe4ac444777bca527bbbcda9eff454d27 Author: Michael Olson <mwolson@gnu.org> Date: Sun Jun 4 19:53:00 2006 +0000 Miscellaneous minor cleanups. darcs-hash:20060604195311-1bfb2-c5ba94841afa0d32c9bc483a21e7c8302c8b9aaa.gz commit 692400a23be7cc13834140638d8d69188917c8f7 Author: Michael Olson <mwolson@gnu.org> Date: Sun Jun 4 19:49:00 2006 +0000 Make sure we never have an empty track description when inserting a song into a playlist buffer. darcs-hash:20060604194940-1bfb2-8e8a20dde4b8c3fc89f5dd0552207cb5f3441429.gz commit 12d4527033257c37e633a1990dc84e2a1ca7f6fb Author: forcer <forcer> Date: Sat Jun 3 12:56:00 2006 +0000 Remove debian-extras package as requested by ftpmasters (debian) darcs-hash:20060603125644-2189f-ff0bdd23bd3b203df37019edae368e4cc97fcb6d.gz commit 1cb8a1f346842a341eb3d336eb9d219bb215f2a3 Author: Martin Schoenmakers <aiviru@diamond-age.net> Date: Thu Jun 1 19:38:00 2006 +0000 Put volume options in their own customize group. Added a separate emms-volume group for customize and put things there instead of in the main thing. darcs-hash:20060601193853-97144-c623003be58dbfc8b5bec359110197e115926c1d.gz commit cff09f0bf5cc55233383a6a8409dd808cd2997f4 Author: forcer <forcer> Date: Wed May 31 00:33:00 2006 +0000 emms-volume.el: Cosmetic stuff, defvar -> defcustom darcs-hash:20060531003343-2189f-8a3926a21e63a49ddf66415e9f17041485dcd721.gz commit 2ecf0171dd396fabfa4b6919ef10b7a561164f0f Author: forcer <forcer> Date: Wed May 31 00:23:00 2006 +0000 emms-volume.el: Minor cosmetic cleanup darcs-hash:20060531002351-2189f-cedd0ca3350a02fc8deda9ec51e1e33f05ab9ecc.gz commit f168ce641347671400a631743681bbdc71bd3c33 Author: forcer <forcer> Date: Wed May 31 00:11:00 2006 +0000 emms-volme.el: Add some requires. darcs-hash:20060531001118-2189f-5d181b45b3ffdfc51c44e17185b3d2d9063475a9.gz commit 25efa815c1e86e9a2cb20c26c73981f410d6a093 Author: forcer <forcer> Date: Wed May 31 00:11:00 2006 +0000 emms-volume-amixer.el: Provide a way to set the control for amixer darcs-hash:20060531001102-2189f-d203d6c92b8e72c7ab8dd380834cba1700815e5f.gz commit 8027bb23119322eaf6c4601fbd4e3ae31b88961f Author: Michael Olson <mwolson@gnu.org> Date: Wed May 31 20:38:00 2006 +0000 Make handling of multiple playlist buffers less error-prone. darcs-hash:20060531203810-1bfb2-7a5c8ca307d33ea501871a6222ab76ad4ada498d.gz commit ec34941c7896238b2219165e2131b7b947f8393c Author: forcer <forcer> Date: Tue May 30 23:07:00 2006 +0000 AUTHORS: Add Martin Schoenmakers. Welcome! :-) darcs-hash:20060530230723-2189f-7716e4510b18f344538deecdfce6810dfc9e035b.gz commit a21f33c5dc56e95d8273ab502907a8b81da6a3e9 Author: Martin Schoenmakers <aiviru@diamond-age.net> Date: Tue May 30 22:35:00 2006 +0000 Add emms-volume and emms-volume-amixer. New files: emms-volume.el provides some general volume changing things, including a minor mode to more easily change volume when not in the EMMS buffer. emms-volume-amixer.el is a backend using amixer. darcs-hash:20060530223500-97144-6c3f95ef335a5f100bc2c6d061a82cb5323b2557.gz commit ac9bb221022b60c987f0caab4be4cfcd99a33964 Author: Michael Olson <mwolson@gnu.org> Date: Tue May 30 19:06:00 2006 +0000 emms-streams: Re-add space after prompt and use completion for type. darcs-hash:20060530190620-1bfb2-ab99409d531e96ce9bc2bca3585a7c193c0b117b.gz commit a5e116b511f233f01cf8cd59908182dee4214112 Author: Martin Schoenmakers <aiviru@diamond-age.net> Date: Tue May 30 13:04:00 2006 +0000 allow nonzero ogginfo exit plus some reindenting When ogginfo gave a nonzero value on exit, any valid data would get tossed if there was any. This prevented emms from showing info for files that are tagged but a bit odd. Also reindented emms-info-ogginfo accordingly, which incidentally removed some tabs in favour of spaces. darcs-hash:20060530130411-97144-7a32c32535a534abdbe173f8f230194c462dbbbd.gz commit 0ff8ab2087e548609e0439cc345e45a8915be064 Author: Michael Olson <mwolson@gnu.org> Date: Tue May 30 14:42:00 2006 +0000 emms-streams: When the user wants emms-streams to play the selected stream instead of add it, create our own playlist buffer. When quitting, if we own the current playlist buffer, kill it. darcs-hash:20060530144243-1bfb2-c740d27615c65016b8516ee90d4db07b7e08fb4a.gz commit a16b4f99aca1581ef60cb7845a706f7c4d7e8e5d Author: Michael Olson <mwolson@gnu.org> Date: Tue May 30 04:54:00 2006 +0000 emms-streams: Re-implement yank and kill so that they do the right thing with emms-stream-list. darcs-hash:20060530045429-1bfb2-e7ae0ff556f6b20d3ab7a28630273308c6ac993c.gz commit e874d110f8a5d15a559fe372a12121547d84c4ac Author: Michael Olson <mwolson@gnu.org> Date: Tue May 30 04:01:00 2006 +0000 emms-streams: Implement kill and yank. darcs-hash:20060530040114-1bfb2-dee2441306ea4d38715338c0cec9d74996238e8c.gz commit 8c031d1890f41173748a3d83dd1f9dd5fc056538 Author: Michael Olson <mwolson@gnu.org> Date: Mon May 29 03:00:00 2006 +0000 emms-streams: Make hitting RET on a URL do the right thing, improve cursor movement, and mark the buffer as unmodified after performing a save. darcs-hash:20060529030043-1bfb2-e17a5b1846d31929013805e31b5722f7e248b86d.gz commit 2bf79de2c33f1f35bafb5b8db8b75af3253b45b8 Author: Michael Olson <mwolson@gnu.org> Date: Thu May 25 01:42:00 2006 +0000 emms-player-mpd: Use more robust method of detecting whether we need to force-feed MusicPD our playlist. darcs-hash:20060525014253-1bfb2-8dc73d1dcd1c3e70703f4a377cfd18d29725c378.gz commit c08efad3544fa9f924dc2d16cd26fb67f5f09804 Author: foo <foo> Date: Wed May 24 20:00:00 2006 +0000 emms-playlist-mode: Make "d" kill the entire line. This seems to be a good compromise of those who use C-k and those who want more standard object-killing behavior. darcs-hash:20060524200008-0beec-44d42e025c9a7a95d740dc87f75aa7a8e3ce0a54.gz commit a665f6aa63b12dd12e0156a8a799dd3a59b39e5b Author: foo <foo> Date: Wed May 24 19:59:00 2006 +0000 emms-player-mpd: When showing the currently-playing song, prepend the name of the radio station, if it exists. darcs-hash:20060524195911-0beec-2b18246bfdc9b627f315860265254332a2197356.gz commit a92fa296433cf56276b070c68ad3b9ecb1d164f9 Author: Michael Olson <mwolson@gnu.org> Date: Thu May 25 03:31:00 2006 +0000 emms-player-mpd: Make seek work correctly. darcs-hash:20060525033120-1bfb2-00e9ea6d64e0c95fcac1105468024881d0a2faba.gz commit 08f9d4ef1c96d8b1075260cfcc61cf8e394a3fa1 Author: Michael Olson <mwolson@gnu.org> Date: Wed May 24 06:16:00 2006 +0000 emms-player-mpd: Fix bug that caused unconditional reloading of the entire MusicPD playlist whenever the track was changed manually. darcs-hash:20060524061655-1bfb2-169e1435160d229391fbeab692180d47458f66c9.gz commit 7a770fa4ab50ae5b7445ec239c7e7375d09d3a24 Author: Michael Olson <mwolson@gnu.org> Date: Wed May 24 05:57:00 2006 +0000 emms-player-mpd: Overhaul for streamlist support, and fix a few miscellaneous issues. darcs-hash:20060524055707-1bfb2-252c06fd98f7b7c5c9b2faae8d109274ca7fc649.gz commit 3fe590d6b34b30a6d76c6a7a888a8fb49debbdaf Author: Michael Olson <mwolson@gnu.org> Date: Wed May 17 03:54:00 2006 +0000 emms-player-mpd: Add a few checks to make sure that the given buffer exists before trying to do anything with it. darcs-hash:20060517035419-1bfb2-3b5eada9a5b8232067d491f2e607ef3ae3e35c3a.gz commit 7cb108237e5ebe3fd996e9587d7d68b3349c90ef Author: Michael Olson <mwolson@gnu.org> Date: Tue May 16 08:12:00 2006 +0000 emms-source-playlist: Do not expand names of files in playlists, as this can cause problems with emms-player-mpd in some configurations. darcs-hash:20060516081257-1bfb2-477dde9d9a2b2430897ee4fe0428a645b3beaa06.gz commit 179c6991624b8b119ee4a35059bac849a1b40f88 Author: Michael Olson <mwolson@gnu.org> Date: Wed May 10 04:07:00 2006 +0000 emms-playlist-mode: Implement the option (disabled by default) of opening a new EMMS buffer for a playlist, when hitting RET on one. darcs-hash:20060510040730-1bfb2-210380685ccbd869f888ace574740f6e18c381b5.gz commit 82878fd44b6c6e37be79a1d33991cecc99cb019c Author: forcer <forcer> Date: Wed May 3 23:43:00 2006 +0000 emms-playlist-mode.el: Don't put a period after the mode map. This hangs 21.4 on display. darcs-hash:20060503234351-2189f-a9506ca448aec033dc5132d490a6b7747d03bf52.gz commit d10f4faee2fa5a5e0b20d90cd86c003188ce8f13 Author: forcer <forcer> Date: Sat Apr 29 19:28:00 2006 +0000 debian/emms-extras.manpages: New file darcs-hash:20060429192811-2189f-ccd14a617c1a32eafc0bc705de1be77f9c5eee63.gz commit 6908b0fbd7d594bcc30cf4d1d05c328cd74878ce Author: forcer <forcer> Date: Sat Apr 29 19:14:00 2006 +0000 Don't delete ChangeLog with make clean, we can't regenerate it without _darcs darcs-hash:20060429191407-2189f-4e5c50ad131187a0b19823550bd223e685bc778c.gz commit f7ffc8f89cd4045488989b825a7cd42ea73d12ab Author: forcer <forcer> Date: Sat Apr 29 19:10:00 2006 +0000 Don't generate ChangeLog in debian/rules - darcs isn't there anymore then. darcs-hash:20060429191044-2189f-2d8a5a05a9e517608c1f7ba2fb3febc2bd1605f3.gz commit 80b0a2f2d2d801bf29d255795e0fa5b22c610024 Author: forcer <forcer> Date: Sat Apr 29 17:47:00 2006 +0000 emms.el: Change version to 2.0 darcs-hash:20060429174710-2189f-e483ea3cf9375be5459bf452536cfa070a4a3c76.gz commit 0100e938655c809e0157acde368c617c885999f2 Author: forcer <forcer> Date: Sat Apr 29 17:45:00 2006 +0000 debian/changelog: 2.0-1 release version. darcs-hash:20060429174536-2189f-5ed0bff26fc0e0c099d93b707be4adaea1db0189.gz commit 8376354696f20d23e04c4a679cf2e94effd555b1 Author: forcer <forcer> Date: Sat Apr 29 18:54:00 2006 +0000 emms-print-metadata.c: Don't segfault if argument doesn't exist. darcs-hash:20060429185448-2189f-d25bfe8317afd3be16e5d2b4cb8c32b0724568e0.gz commit 972e4c0446146b457e39cb5e3734404141aed533 Author: forcer <forcer> Date: Sat Apr 29 18:41:00 2006 +0000 emms-print-metadata.1: New file. darcs-hash:20060429184129-2189f-d782b559f69380f77746cd7eb2a8a6d56e153cb3.gz commit 227fb23c0e0fbc25685aba46a991493a7decb001 Author: forcer <forcer> Date: Sat Apr 29 18:39:00 2006 +0000 Install correctly with Debian _and_ make install. darcs-hash:20060429183958-2189f-44de028e3face57316a1485fc9e09d29ecceb7eb.gz commit f49efbf33b4f5b00c4c4763e90919ad8a5ecf928 Author: Michael Olson <mwolson@gnu.org> Date: Sat Apr 29 13:42:00 2006 +0000 emms-playlist-mode: Call kill-line instead of kill-region to fix a minor bug. darcs-hash:20060429134204-1bfb2-f7123e0f564cda7a675e8bf745f54f8bdbd968ff.gz commit fa148fc3c344022c1f4011a6c4da9441ae0849f6 Author: Michael Olson <mwolson@gnu.org> Date: Tue Apr 25 19:15:00 2006 +0000 Rename with-widened-buffer to emms-with-widened-buffer. darcs-hash:20060425191558-1bfb2-7bbb4ba814a5a83a3bf6b7f839ec2b824def9ae8.gz commit e707bd9a77d7ed676cf8da92415318505532b7cf Author: yoni-r <yoni-r> Date: Tue Apr 25 11:46:00 2006 +0000 fixed Makefile darcs-hash:20060425114636-6ce53-dddce4f16a9318fd80d798dfe1c567c477ea9538.gz commit e57195633dabb65ea67d39b1fc58958e8f4a544c Author: Michael Olson <mwolson@gnu.org> Date: Tue Apr 25 14:27:00 2006 +0000 emms-playlist-mode: Add face entries for light backgrounds. darcs-hash:20060425142716-1bfb2-14d6aca08e78c48bad74b52baf680dbc7f22413a.gz commit a051095baa3bb9f50be8b8232a46bce12c03600c Author: forcer <forcer> Date: Sun Apr 23 20:19:00 2006 +0000 emms.el: Simple playlists shouldn't be bothered by read-onliness. darcs-hash:20060423201939-2189f-806d03d345e7c8194afada0d344a3cf8e51d6e5e.gz commit a4b2dff4a3d5bdb43c71615c9d5aec86767cdd14 Author: forcer <forcer> Date: Sat Apr 22 13:28:00 2006 +0000 emms.el: Fix docstring of emms-player-finished-hook. darcs-hash:20060422132832-2189f-abbc2b41123ede5d7277719a548be8b1e0698310.gz commit da81b58374f0545b3eb36a99663b4060f6b503fa Author: Michael Olson <mwolson@gnu.org> Date: Sat Apr 22 03:48:00 2006 +0000 emms-player-mpd: Add disconnect function, for when you want to keep playing music, but not keep track of it in Emacs. darcs-hash:20060422034842-1bfb2-9734c53ac157fae7082044e110077989db12778e.gz commit 45b3a842832d82144011e34b455634465432a88d Author: lucas <lucas> Date: Fri Apr 21 19:19:00 2006 +0000 emms-metaplaylist-mode.el: New keybinding to emms-metaplaylist-new-buffer. Yes, it's a small patch... darcs-hash:20060421191956-4f952-1094d9640dfb4be8fc2f146de10f0fbe07e4099a.gz commit 7cec9d03b8941c466afc773e6ae96b65d6ef0533 Author: Michael Olson <mwolson@gnu.org> Date: Fri Apr 21 22:47:00 2006 +0000 emms-player-mpd: Make sure that emms-player-finished-hook is called once the playlist is exhausted. darcs-hash:20060421224715-1bfb2-33f5e3e65bff53f48a17854f3ba31f196ed290cb.gz commit 45115aee206a609edc51656190220a443fed0ee3 Author: Michael Olson <mwolson@gnu.org> Date: Fri Apr 21 21:51:00 2006 +0000 emms-player-mpd: Prompt for volume change amount. darcs-hash:20060421215128-1bfb2-18736498b4feb9f24be75d880a0180b2b8cd5138.gz commit 08d369cedee786f4614e1b9210cb3c78741361f3 Author: Michael Olson <mwolson@gnu.org> Date: Fri Apr 21 21:43:00 2006 +0000 emms-player-mpd: Implement and document support for changing the volume. darcs-hash:20060421214306-1bfb2-44c50b54640c68005184d312ea975c7cb77e629d.gz commit 6bd53f5563cc1a4cfe9cb50b54e9f14e289a9f45 Author: lucas <lucas> Date: Thu Apr 20 22:41:00 2006 +0000 emms-metaplaylist-mode.el: new function : emms-metaplaylist-set-active to set the active playlist buffer from the metaplaylist menu darcs-hash:20060420224114-4f952-b6612b4c3c720fb6799f43796603b096ac6ab513.gz commit e14816295f37f7c03531b16cbba95bcaaac82a74 Author: lucas <lucas> Date: Thu Apr 20 22:31:00 2006 +0000 emms-metaplaylist-mode.el: new function to create a new empty EMMS playlist. darcs-hash:20060420223126-4f952-0ed23bd23c06cf7febd995919cb8b95b75b01765.gz commit 13ff7c02ef108cd42a673070f5d8989cea1c8302 Author: Michael Olson <mwolson@gnu.org> Date: Fri Apr 21 11:34:00 2006 +0000 Update AUTHORS. darcs-hash:20060421113456-1bfb2-a4d6178410dd2251617c36732819d1737dec4efb.gz commit 8030081c1ac0a7e849780f2af9ca6632ce9bc21e Author: Michael Olson <mwolson@gnu.org> Date: Thu Apr 20 23:57:00 2006 +0000 emms.el: Fix compiler warning for Emacs22. darcs-hash:20060420235746-1bfb2-6441ee307970da64129ecec07effb3d09acbad2b.gz commit a33158e96b8da3e4be465baac2e918f9127a5559 Author: Michael Olson <mwolson@gnu.org> Date: Thu Apr 20 23:47:00 2006 +0000 Make XEmacs21 and Emacs21 happy. darcs-hash:20060420234749-1bfb2-e458134b41ba8e28d25030fe5b6d6b8f4222c28d.gz commit 6e194a2d2a308faac79be89e26b6a49fe04e6717 Author: forcer <forcer> Date: Thu Apr 20 23:07:00 2006 +0000 Move propertize compatibility function to the others. darcs-hash:20060420230737-2189f-ba23ce86a96b3da64f5642790f0e839f01f9f406.gz commit 08471d5e769d67f6d9f7b908d7c04b7c4d09837c Author: Michael Olson <mwolson@gnu.org> Date: Thu Apr 20 22:38:00 2006 +0000 emms-player-mpd: Use better default for emms-player-mpd-supported-regexp. darcs-hash:20060420223819-1bfb2-4a2d9318ab7af9b5ca3fbbd7843d1d44dd938994.gz commit 244e5efb47ff0996654a463f58a71dc50ed8939b Author: Michael Olson <mwolson@gnu.org> Date: Thu Apr 20 22:26:00 2006 +0000 emms-player-mpd: Use better check to see if we are given valid output from "mpd --version". This should improve results for the case where mpd is installed on a different machine. Thanks to Adam Sj[_\c3_][_\b8_]gren for the report. darcs-hash:20060420222600-1bfb2-6cbb1667e10978e848a64bb58dcec3388aa26819.gz commit 56ab07f294567f494eded602b83761e6a2b8ab83 Author: forcer <forcer> Date: Thu Apr 20 21:09:00 2006 +0000 Use %S not %s for tracks in errors. darcs-hash:20060420210952-2189f-a4ce15ed5c5696a4e5ac42b050256b9eba7a8d2b.gz commit 5d1019b4d8866e2a00dcb6410aea212a61946db6 Author: forcer <forcer> Date: Thu Apr 20 21:07:00 2006 +0000 Provide emms-propertize compatibility function. darcs-hash:20060420210744-2189f-c648403a30e0c47d63986e7378d122c7d811aab9.gz commit 56ad988565352e3084774b2d40150e13cbbe3c0a Author: forcer <forcer> Date: Thu Apr 20 20:10:00 2006 +0000 Fix face definitions syntax (emms-playlist-mode, emms-metaplaylist-mode) darcs-hash:20060420201021-2189f-697d166a50c7e62f09abbbaf4ce0dd17ab9084ff.gz commit df33a9de0b079846589ade4322fff4ae3bda16ce Author: william.xwl <william.xwl> Date: Fri Apr 14 11:45:00 2006 +0000 Added `emms-playlist-sort-by-natural-order'. Thanks to Matthew Kennedy <mkennedy@gentoo.org>. darcs-hash:20060414114543-e8fe6-c2c4b3e74d65da96ad36eb70c2aefaa742a52c27.gz commit 38424da232f995ee42b0262a1dc891042ea55acf Author: lucas <lucas> Date: Thu Apr 13 16:14:00 2006 +0000 emms-libtag.el : Make it id3v1 friendly by removing all the trailing whitespace in metadata darcs-hash:20060413161451-4f952-95af88eaf6095d7459019458ca6131aa9f7d61e0.gz commit 234190f338439c84bc5d58aeaced264efaa424d4 Author: Michael Olson <mwolson@gnu.org> Date: Wed Apr 12 05:26:00 2006 +0000 emms-player-mpd: Don't start the timer upon playing a track if `emms-player-mpd-sync-playlist' is nil. darcs-hash:20060412052632-1bfb2-8733e8d42b9c6a006c09087655f0a4d59a11e877.gz commit b18fa304660f9cf4ce66a79834763e471adf0b40 Author: Michael Olson <mwolson@gnu.org> Date: Wed Apr 12 03:51:00 2006 +0000 Make `emms-player-started' function, which serves the same purpose as `emms-player-stopped', in that it is meant to be called by the player. emms-player-mpd needs this so that it can tell EMMS exactly when playback has begun. darcs-hash:20060412035132-1bfb2-d4982d0b49ca4b949c353f2702ceca4318078bb3.gz commit 85576f435200a8a40686e78fda148cf4047fba3b Author: Michael Olson <mwolson@gnu.org> Date: Wed Apr 12 03:29:00 2006 +0000 emms-player-mpd: Make last compiler warning go away with some `put' trickery. darcs-hash:20060412032926-1bfb2-1aae9faa36ff47ed53027cf5bfc4871adc7248b7.gz commit 9bc8c6f54c74e2b37a79358aad28409b0d79a74c Author: Michael Olson <mwolson@gnu.org> Date: Wed Apr 12 03:26:00 2006 +0000 emms-player-mpd: Make emms-player-mpd-show take a callback argument so that it's easy to make a /NP command for Emacs-based IRC clients. darcs-hash:20060412032655-1bfb2-bdc259d8c5b1210435d72a487e8ac756377d780f.gz commit 4972da8265bd1aaf02fb5296c013d5ca6b35d28d Author: Michael Olson <mwolson@gnu.org> Date: Tue Apr 11 22:54:00 2006 +0000 emms-player-mpd: Set timer interval to be 1 by default and adjust docstring. darcs-hash:20060411225417-1bfb2-f7db6dfb4664a2f57de8e3cd415a49abe36cf76c.gz commit 640c4753038283d32b28c242b382ab6ff124f5db Author: forcer <forcer> Date: Mon Apr 10 12:26:00 2006 +0000 emms-source-file.el: Fix dired source. darcs-hash:20060410122652-2189f-45a475ba6dcf5ed0ac492d2052bebba6cd6d5938.gz commit 6618771242832290c6bca0f8c0ce944e04780750 Author: forcer <forcer> Date: Mon Apr 10 12:26:00 2006 +0000 emms.el: Introduce and use `emms-source-old-buffer' darcs-hash:20060410122623-2189f-b75ebb39924d04ffdaddb7dae6f3f303f493a950.gz commit 0d64f1dc19471d0a6343a89703292d88131761b4 Author: Michael Olson <mwolson@gnu.org> Date: Tue Apr 11 04:10:00 2006 +0000 emms-player-mpd: Fix minor typo in comments. darcs-hash:20060411041037-1bfb2-73ab388007c8c81b890d1427e0aa0f6f39e115b6.gz commit dd04c73ba141c1b95fda50f7ed38b67ecd979171 Author: Michael Olson <mwolson@gnu.org> Date: Tue Apr 11 03:35:00 2006 +0000 emms-player-mpd: Make sure inserted text from emms-player-mpd-show goes to the right buffer. darcs-hash:20060411033552-1bfb2-f36fa15e202b91248e594a2485d170ff5c1ed8bb.gz commit a92a2f806e3d38a91730d8ca8558282f23f6b651 Author: Michael Olson <mwolson@gnu.org> Date: Tue Apr 11 03:05:00 2006 +0000 emms-player-mpd: Remove obsolete option. darcs-hash:20060411030539-1bfb2-7a0cb0680a654d0eda136fb70006c8ec47d257ed.gz commit b59d18fb1184b3af67240c04dda9a99b9c91a114 Author: Michael Olson <mwolson@gnu.org> Date: Tue Apr 11 03:00:00 2006 +0000 emms-player-mpd: Reset some extra state data on stop. darcs-hash:20060411030023-1bfb2-b53f8e516de55cdd2a7003def861323523971cb7.gz commit 4dc6b1a629bc707b9ab8be5064b5c038a50a7aa9 Author: Michael Olson <mwolson@gnu.org> Date: Tue Apr 11 02:59:00 2006 +0000 emms-playlist-mode: Fix a bug where too many overlays were being added when the track was updated. darcs-hash:20060411025931-1bfb2-71b7e3fe4999d77752bae448c5c34784c9db2d33.gz commit 9d8fa5e231319db1fcd04fe3c2aec6313457f1fd Author: Michael Olson <mwolson@gnu.org> Date: Tue Apr 11 01:39:00 2006 +0000 emms-player-mpd: A few minor tweaks. darcs-hash:20060411013942-1bfb2-ca3de09dfd6aaae5dcd5b6dd2870b12a49aba2e1.gz commit 634ba8e1c2b60f338f2ec3ca94a69fd02e19f2f0 Author: Michael Olson <mwolson@gnu.org> Date: Tue Apr 11 00:43:00 2006 +0000 emms-player-mpd: Major rewrite to use a custom transaction queue implementation, which includes adjusting most functions to use callbacks and closures. darcs-hash:20060411004345-1bfb2-c423044aff0c53d3c26269d43c9f6827f66973f5.gz commit db10180b8bf08bc7fc69773025deb6a0a20c0176 Author: Trent Buck <trentbuck@gmail.com> Date: Sun Apr 9 20:55:00 2006 +0000 patch resolution darcs-hash:20060409205547-8f417-949ecd292c7800526e6195dbf3c11c1a33aee032.gz commit 65642af528f886fae0e370fa511b6fb150df4a5e Author: trentbuck <trentbuck> Date: Sun Feb 26 05:54:00 2006 +0000 emms-player-mplayer.el: mplayer supports FLAC, too. darcs-hash:20060226055450-4ef00-88ce790a489db5ea89d3621b5d3f02ac5ff46e0a.gz commit 0a72e5435bc9d4fbacc330d334b5cf967908f2d0 Author: Trent Buck <trentbuck@gmail.com> Date: Sun Dec 4 18:13:00 2005 +0000 emms-info-libtag.el: remove unused variables. darcs-hash:20051204181347-8f417-cc6b45daa751bbd6189ff6f8c880979a8b5495ad.gz commit 3da0c9985e451937653b89ffa5c74d2f7dfa2b03 Author: Trent Buck <trentbuck@gmail.com> Date: Sun Nov 20 06:50:00 2005 +0000 emms-info-libtag.el: libtag can also handle Speex files. darcs-hash:20051120065009-8f417-8fc080259fe51b3e579026b9c9d0bed0d0c759d3.gz commit 9e13d9a4b8408e8af40793b84328377c4442354d Author: Michael Olson <mwolson@gnu.org> Date: Sun Apr 9 05:25:00 2006 +0000 emms-playlist-mode: Remove obsolete function. darcs-hash:20060409052556-1bfb2-050df934eda6f883117367049ac996161a221037.gz commit 440e4491dd9b32fa589479029e2c51e396c6fcb4 Author: Michael Olson <mwolson@gnu.org> Date: Sun Apr 9 00:53:00 2006 +0000 Add new playlist sources to documentation. darcs-hash:20060409005306-1bfb2-d3512df73bfefc5371cd57bdab6c4552fa56677d.gz commit 8ba97c551f289c509140f29e075d0e3a657f66f3 Author: Michael Olson <mwolson@gnu.org> Date: Sun Apr 9 00:52:00 2006 +0000 emms-playlist-mode: Use emms-playlist-save instead of a custom function. darcs-hash:20060409005234-1bfb2-f2422fc74d0b1fc065c00647cb71e247e181bf10.gz commit 2d70d0a638b8b1f790674ef7e31efb44ca671b0d Author: Michael Olson <mwolson@gnu.org> Date: Sun Apr 9 00:35:00 2006 +0000 emms-source-playlist: Get things working to my satisfaction, like saving playlists in different formats and (optionally) being prompted for which format. darcs-hash:20060409003540-1bfb2-4aedadb4bc109afb1aaf6b96530e61d6a9f19201.gz commit d03e7d69061e98ae1b807a5a3e57ba4bd4e72885 Author: Michael Olson <mwolson@gnu.org> Date: Thu Apr 6 04:26:00 2006 +0000 emms-playlist-mode: Make it possible to use edebug on `with-inhibit-read-only' forms. darcs-hash:20060406042615-1bfb2-4b1552442730fef820796f1c93cdb5c62a8b08b2.gz commit 9a59fa35c1a9a165c0aad92eb24738ee4c5e1136 Author: Michael Olson <mwolson@gnu.org> Date: Thu Apr 6 03:45:00 2006 +0000 emms-player-mpd: If the MusicPD daemon goes away, make sure that we can still stop EMMS. darcs-hash:20060406034553-1bfb2-7a900012bcfc586c2b38632345da30e6af72b733.gz commit 1ad6f6d51ebbb64a117c12adbb298cce4d816cfb Author: william.xwl <william.xwl> Date: Mon Apr 3 14:04:00 2006 +0000 Updated manual for emms-lyrics. darcs-hash:20060403140416-e8fe6-e783c9fdc7420f7f1b6bc94642a80e86d2f251e1.gz commit ff4bd16b5db79f53d55637724afe413aa100e372 Author: william.xwl <william.xwl> Date: Mon Apr 3 13:49:00 2006 +0000 New variable: `emms-lyrics-coding-system'. It's the coding system used in the output of lyrics. (I sent this before, maybe some unexpected problem happened.) darcs-hash:20060403134922-e8fe6-5b1bb0825a3f5f6616024226d1d0c6015c3aa83c.gz commit 2ae7913992e5a562771194de52b1e92168b51781 Author: Michael Olson <mwolson@gnu.org> Date: Sun Apr 2 18:48:00 2006 +0000 emms-player-mpd: Never set emms-player-stopped-p, since this is only to be done when the user explicitly stops the music. darcs-hash:20060402184833-1bfb2-1ce9edcaafb39aa44a92a0e80c606568c57546ca.gz commit 29907737af89a046bd8f8e87ef83e7ccae8687ab Author: Michael Olson <mwolson@gnu.org> Date: Sun Apr 2 17:50:00 2006 +0000 Make sure that negated character classes in regexps include the newline character, so that there is no possibility of empty lines being matched. darcs-hash:20060402175002-1bfb2-9f7ccf9489b3688d660b612a7243fe42e87e84e7.gz commit 6c31e5abefd41045f9325827f6976d790f12fa82 Author: forcer <forcer> Date: Sun Apr 2 16:05:00 2006 +0000 emms-playlist-sort.el, quote FORM argument to eval-after-load darcs-hash:20060402160555-2189f-b7becf7694117b1aacfcc1a40410e4087ca951e3.gz commit 872f8b1a4006a031149f3b38121a66d6397162a8 Author: Michael Olson <mwolson@gnu.org> Date: Sun Apr 2 14:44:00 2006 +0000 Update manual and emms-setup with the preferred way of invoking emms-playing-time and emms-lyrics from .emacs. Update MusicPD section of manual. darcs-hash:20060402144407-1bfb2-857e5408fe3df2dffd111150018b3bbf60436679.gz commit b9466bfe9813f555c7a589867f0f4153731693ea Author: Michael Olson <mwolson@gnu.org> Date: Sun Apr 2 03:15:00 2006 +0000 emms-streams: Make some options customizable. Fix compiler warnings. darcs-hash:20060402031546-1bfb2-9244eec3e8dc3890f2640a1f1f01a18309b9ae4d.gz commit 7f7223d6655e67e4e75d54bbd57f04a47b65dba3 Author: Michael Olson <mwolson@gnu.org> Date: Sun Apr 2 02:45:00 2006 +0000 emms-source-playlist: Add support for m3u and pls playlists. darcs-hash:20060402024556-1bfb2-da264c4af634159a12fed0e3e4425eb238b9c917.gz commit e1d5bf36570590809922d759be087be97ecd4d43 Author: lucas <lucas> Date: Sat Apr 1 19:04:00 2006 +0000 README: Added a paragraph about libtag. darcs-hash:20060401190443-4f952-6d2860b0aa971dace2ff643937e2071209c10712.gz commit 9d41c3807c00593c7c18bd144712ce2a0a414dd6 Author: lucas <lucas> Date: Sat Apr 1 18:54:00 2006 +0000 emms-info-libtag.el: Add a warning about the possible conflict with emms-info-mp3info darcs-hash:20060401185421-4f952-ca0419414afbe93766a07c7e396d4ac8cf586f44.gz commit c7ff450e200e3ee324c26d8752bc90e672552789 Author: lucas <lucas> Date: Sat Apr 1 18:18:00 2006 +0000 Some minor modifications darcs-hash:20060401181821-4f952-37cc54e5cdd7ce1db9a81e2d45cdc3e1762c497b.gz commit 843dfee3364438d0f8dbbe8486136bcf1dc9949f Author: forcer <forcer> Date: Sat Apr 1 20:51:00 2006 +0000 Use insert-file instead of insert-file-literally to get around coding system problems darcs-hash:20060401205125-2189f-ebdde0312212cab3bae813796b9d79ae9ce1001b.gz commit 215607ef80022605cad09106bb7748aa089435ce Author: forcer <forcer> Date: Sat Apr 1 20:43:00 2006 +0000 Added emms-play-playlist darcs-hash:20060401204306-2189f-3e4d369e25d12e99382d3ab51c9e05d88c768f82.gz commit 4d0be4b900c878607600a915a0b7f371b9a557bf Author: Michael Olson <mwolson@gnu.org> Date: Sat Apr 1 23:31:00 2006 +0000 Remove emms-tageditor.el, since it only works with emms-pbi.el. It might be useful to re-add this, once it has been rewritten. But first, let's get a release out the door :^) . darcs-hash:20060401233146-1bfb2-a463cb4bfd32568f171ff0ac95edfe1f8757ab91.gz commit b8ff219abfe062695d166e4e6013740dc3e9446e Author: Michael Olson <mwolson@gnu.org> Date: Sat Apr 1 23:30:00 2006 +0000 emms-player-mpd: Don't use define-emms-simple-player, since we provide our own versions of the functions that it produces. darcs-hash:20060401233036-1bfb2-a67d7b4d6de02703fde818b9db9342445ba7428d.gz commit d28577592c5b8c1857faaa8a43fce46d7462e924 Author: Michael Olson <mwolson@gnu.org> Date: Sat Apr 1 23:29:00 2006 +0000 emms-lyrics: Make this behave like other add-ons. darcs-hash:20060401232918-1bfb2-44563a9e0e4801d9af65d82019631d3fdec2a1a8.gz commit 438e7ec52497afc1aa5799f13d83156ccfda1f15 Author: Michael Olson <mwolson@gnu.org> Date: Sat Apr 1 23:26:00 2006 +0000 Fix a variety of compilation errors and warnings. darcs-hash:20060401232610-1bfb2-5fe5e4892c94e29a59738bf0d27e7e91ad68f2ed.gz commit da7d1d0ebae7e4b6d8027a7fec3eef0c3816f2b6 Author: Michael Olson <mwolson@gnu.org> Date: Sat Apr 1 23:25:00 2006 +0000 Makefile: Don't show Emacs commandline. Remove generated HTML file in clean rule. darcs-hash:20060401232522-1bfb2-472b1a3fa77db3d21f53fde078a28c371fb7c992.gz commit 1553d6a08d5c6432cfd5343dda8e7b7b57536362 Author: Michael Olson <mwolson@gnu.org> Date: Sat Apr 1 21:08:00 2006 +0000 emms-streams: Add prefix to utility functions. darcs-hash:20060401210849-1bfb2-e22b7fcd606225ad83303472525860d0e66fb6dc.gz commit bf80e02cd233409d56580bf38cc76ef58fc0f24e Author: Michael Olson <mwolson@gnu.org> Date: Sat Apr 1 21:06:00 2006 +0000 Make all add-on files toggle-able. darcs-hash:20060401210634-1bfb2-6a8f735119b68c6ab80d503910ec0105680fec73.gz commit f2c85795a7b5c7e992b08c889ad563bce56f9ae2 Author: forcer <forcer> Date: Sat Apr 1 20:38:00 2006 +0000 Added emms-source-playlist.el, moved stuff from emms.el there darcs-hash:20060401203820-2189f-7dae5d0fc14543654aef72ba3f1ab72ff94c82e0.gz commit e41edcad7947fab43b17cae064ae617d0162f783 Author: forcer <forcer> Date: Sat Apr 1 18:59:00 2006 +0000 Move emms-parse-playlist to emms-source-file.el, rename to emms-source-file-parse-playlist darcs-hash:20060401185913-2189f-75ccf31626867407f72de64642d6fc020cfc240e.gz commit e539ab44dad0dfe282ef6cc4e30800cdbbb7be8d Author: Michael Olson <mwolson@gnu.org> Date: Sat Apr 1 19:43:00 2006 +0000 Remove emms-pl-manip.el darcs-hash:20060401194358-1bfb2-a0337e3a56ff8ad1628bea20f2eb65890142bdef.gz commit 36357c391c09fa2590f99db4695644cb23b006b5 Author: Michael Olson <mwolson@gnu.org> Date: Sat Apr 1 19:33:00 2006 +0000 Remove emms-pbi*.el at forcer's request. darcs-hash:20060401193306-1bfb2-0e64e29a1c75efe182c6e77f2bd17327cd209b73.gz commit ca867192b76b7e10f1672cdd1fa7862eb2f40341 Author: Michael Olson <mwolson@gnu.org> Date: Sat Apr 1 19:18:00 2006 +0000 emms-mode-line: Add toggle functions and autoload cookies. darcs-hash:20060401191825-1bfb2-763dcaee4201c44565e113e516b844e448a0c4a1.gz commit e9cfafc1da50e7ea469a3ed58add63b7785f09ae Author: Michael Olson <mwolson@gnu.org> Date: Sat Apr 1 19:04:00 2006 +0000 emms-player-mpd: Use simpler value for connect function. darcs-hash:20060401190427-1bfb2-b1a08aa97de633cb891a4601d9ecf8f2015a4262.gz commit fd8f2d49c6dff5b2be10bf1c67332d6e2f6e357c Author: Michael Olson <mwolson@gnu.org> Date: Sat Apr 1 18:45:00 2006 +0000 Makefile: Use correct extension in new HTML rule. darcs-hash:20060401184547-1bfb2-c119fbec8e989ae49dd7081fb2bdf7240026f0c2.gz commit a3f190996829a77d75e3bb030efcef79f08a6fc6 Author: Michael Olson <mwolson@gnu.org> Date: Sat Apr 1 18:03:00 2006 +0000 Makefile: Update .PHONY, add .PRECIOUS line for generated files, add rule for creating HTML version of documentation. darcs-hash:20060401180331-1bfb2-44d539a5c9152d23c80c2107bebb5c67cccebee5.gz commit ab304cef4912461160100f2c79ee0c121f1b0fd2 Author: forcer <forcer> Date: Wed Mar 29 05:07:00 2006 +0000 emms-streams.el (emms-stream-default-list): Add "Voices from Within" darcs-hash:20060329050712-2189f-ec7a17ad015b924234a61a4678f5ee967adcd97d.gz commit 05b4e0040a004828183d76befd3518b445c84364 Author: yonirabkin <yonirabkin> Date: Fri Mar 24 23:25:00 2006 +0000 All stable extentions documented darcs-hash:20060324232506-be80e-e613107612d172e28a631a707b2a892e1121ac80.gz commit 22284f3dc9f47e26db32901d5528d4ab78aa75f4 Author: Michael Olson <mwolson@gnu.org> Date: Sun Mar 26 23:00:00 2006 +0000 emms-player-mpd.el (emms-info-mpd): Prevent an error when we can't connect to a MusicPD instance. This prevents EMMS from causing Emacs to stop reading initialization settings. darcs-hash:20060326230003-1bfb2-0f3bba7ce910dfd287a640fa35288b7027bc6b21.gz commit fa07ba5436dbca2c401dc6f00f5c5842b8827e77 Author: yonirabkin <yonirabkin> Date: Thu Mar 23 16:48:00 2006 +0000 Added MusicPD to the Emms manual. darcs-hash:20060323164844-be80e-c8318152b9ff24a05bbfed0f5a113836393e5f3c.gz commit 8ace62a9927e23b188e25b5464c82351a4b92fa2 Author: yonirabkin <yonirabkin> Date: Thu Mar 23 12:53:00 2006 +0000 Added `emms-playlist-sort' to the Emms manual. darcs-hash:20060323125334-be80e-cba5ae5567623d231f81df0b1331905cd9ccf50f.gz commit 147707e5c30059c297ee448c915627e377cff6a6 Author: yonirabkin <yonirabkin> Date: Wed Mar 22 10:46:00 2006 +0000 re-organization of emms-setup levels darcs-hash:20060322104611-be80e-ea1f212093c000e3d33d6b497bb1a75fb63bcbae.gz commit bc984744c80745e666d9ef76b7076eb673a2e67c Author: Michael Olson <mwolson@gnu.org> Date: Thu Mar 23 13:51:00 2006 +0000 emms-player-mpd: Make importing of MusicPD playlist a bit less error-prone. darcs-hash:20060323135109-1bfb2-bf5417002b601172af920c21a90a1a26e6e79cb9.gz commit f128ac46140f1aa171a2f6f703693485e6a451c4 Author: Michael Olson <mwolson@gnu.org> Date: Mon Mar 20 07:13:00 2006 +0000 emms-player-mpd: Make pausing work after importing a playlist from MusicPD. darcs-hash:20060320071337-1bfb2-7bba470fcb6076795954f2a73bb86b985ffd46e4.gz commit d580c73fbef1c4cc21cd1638b4581021df32a3c3 Author: Michael Olson <mwolson@gnu.org> Date: Mon Mar 20 06:51:00 2006 +0000 emms-player-mpd: Try to get values for name and port from environment. Fix awkwardness in `emms-player-mpd-block'. darcs-hash:20060320065153-1bfb2-0f6c4fa2e86903e84a5ea2adebc249eda01f7b2a.gz commit a40c9d74e6b973ace486493bd521dec78d253b9e Author: Michael Olson <mwolson@gnu.org> Date: Mon Mar 20 06:14:00 2006 +0000 emms-player-mpd: Implement importing the current MusicPD playlist into EMMS and fix a couple of bugs. darcs-hash:20060320061455-1bfb2-d2213d8b9051a7bd03cf23d560590dfbff4c612b.gz commit 7474e8844ce76b50941d7a22fa03f749dde9b1e1 Author: yonirabkin <yonirabkin> Date: Wed Mar 15 19:07:00 2006 +0000 finished updating copyrights darcs-hash:20060315190720-be80e-ab0de489504975286f9c2cd9d1359c0345a5f7cb.gz commit a86a7af5251d6ad2f4557889a720bf678dbefded Author: yonirabkin <yonirabkin> Date: Wed Mar 15 15:58:00 2006 +0000 fixed copyright years and copyright holder darcs-hash:20060315155834-be80e-cda533a1510f20fdef5248ec0037ddaa037fa18b.gz commit dfbd6f4035ca319f417c9d730d1daf5bcce4dfef Author: forcer <forcer> Date: Mon Mar 6 21:15:00 2006 +0000 emms-source-file: Yes, playlist does work. (Removed comment) darcs-hash:20060306211535-2189f-cb714d0f47ff666b1a2a6a19e63691d8b5d7ff66.gz commit e0013a77c5b26f59a87470f2f0ad48d49739ee02 Author: forcer <forcer> Date: Sun Mar 5 15:49:00 2006 +0000 emms-player-simple.el (alsaplayer): Fixed regexp. darcs-hash:20060305154938-2189f-e2553a0d4703dc15d855a0f4168b0bf7a0977a85.gz commit d28cb19d4e0672d89479011c58a26d2b50b039d6 Author: forcer <forcer> Date: Sun Mar 5 04:52:00 2006 +0000 emms-player-simple.el: Added alsaplayer support. Thanks to indio on #emacs. darcs-hash:20060305045259-2189f-6ddff373f70f9b9e2ae305211326eebe51a85dff.gz commit d06ba122a54cbd5a59592d3f01b3202c7b3f8c47 Author: Michael Olson <mwolson@gnu.org> Date: Thu Mar 2 03:23:00 2006 +0000 emms-player-mpd: Do a seek when the song has changed in case several seconds have elapsed between detection and song change. darcs-hash:20060302032315-1bfb2-04999c8395e8a22d602098f529914ae93b44d62c.gz commit 0d2dc943cd9d4b71e2428fa20e0e94b0d5d84012 Author: yoni-r <yoni-r> Date: Sun Feb 26 17:11:00 2006 +0000 playlist mode yank bug fix darcs-hash:20060226171121-6ce53-3e11dc88eab5e66338855da2654cb3f8b742a776.gz commit 79f9c4209fe910df32fbd4e06e8f8254bb0b5589 Author: yoni-r <yoni-r> Date: Thu Feb 16 18:18:00 2006 +0000 update README file darcs-hash:20060216181847-6ce53-04e7a1078c0eb8e134ad7b20d0d37ed751407c4c.gz commit 69a77df5a61a42a460d10ae60c1d41616940eed1 Author: william.xwl <william.xwl> Date: Wed Jan 18 13:14:00 2006 +0000 Pass correct parameter to `run-at-time', to make sure only one timer is running. darcs-hash:20060118131412-e8fe6-d423f6a7aa50b929403fc333984280e137b6b8fe.gz commit 1de710aba20ad287c7e39d9b0b3804b339e6823a Author: yonirabkin <yonirabkin> Date: Mon Jan 9 08:38:00 2006 +0000 add two macros, one to emms.el and the other to emms-playlist-mode.el. The former fixes a bug in which the software attempts to access a completely narrowed buffer and the latter because it looks nicer. darcs-hash:20060109083856-be80e-475149a8911856cab9d2dd6f5143381c53afdcae.gz commit cf246d4690f5e776604f250547c96e51599c1020 Author: Michael Olson <mwolson@gnu.org> Date: Sat Jan 7 08:10:00 2006 +0000 emms-player-mpd: Detect when the server has stopped, and call emms-player-stopped. darcs-hash:20060107081052-1bfb2-8328797f81d3e794af03ef03521107161d74563f.gz commit 5481c98e4b4099f30bc5764ce2b252581a303214 Author: Michael Olson <mwolson@gnu.org> Date: Sat Jan 7 06:43:00 2006 +0000 emms-player-mpd: Implement blocking so that code in timers doesn't conflict. darcs-hash:20060107064358-1bfb2-3725a5776e4ad64196f8f9a0a0d08bd065e69d01.gz commit b215622aad016d7e39fda64809579bf2be0d3783 Author: Michael Olson <mwolson@gnu.org> Date: Sat Jan 7 05:33:00 2006 +0000 Rename m3u-playlist source to "playlist" and support .pls files. The playlist-parsing routine has been moved to a separate function, since the MusicPD player also needs to use it. Detect URLs in playlists and use type of 'url when creating tracks for them. darcs-hash:20060107053310-1bfb2-dc5bf155e440294ee4a91b08033fa4b4242695ab.gz commit 65dc3b56ef44b83fcb4f87cf8bf397fe0a8402e8 Author: Michael Olson <mwolson@gnu.org> Date: Fri Jan 6 03:24:00 2006 +0000 Use emms-replace-regexp-in-string. darcs-hash:20060106032400-1bfb2-7036a03bfa98f5379e95bb61848c497de43b3be6.gz commit 6181ec571579b78c12424a7f55347be6b24f169c Author: Michael Olson <mwolson@gnu.org> Date: Fri Jan 6 03:21:00 2006 +0000 emms-player-mpd: Escape specials in filenames like the other MPD clients do. darcs-hash:20060106032121-1bfb2-ff568ec3dbc6ef6477c89e20d9af1bdffc0b48a7.gz commit 60f527e70b40ecbf7cd6fef39e58acdc3ae3c87b Author: Michael Olson <mwolson@gnu.org> Date: Fri Jan 6 03:20:00 2006 +0000 emms-stream-info: Use emms-replace-regexp-in-string. darcs-hash:20060106032048-1bfb2-397168fc645c02324e27a8721dae9d28ab5b23c7.gz commit 4b913cf81982670faadaa3f9672a60e8ea63e720 Author: Michael Olson <mwolson@gnu.org> Date: Thu Jan 5 17:21:00 2006 +0000 New XEmacs compatibility function: emms-replace-regexp-in-string darcs-hash:20060105172144-1bfb2-36678408233ea377cc5b7deda59d37362948a78b.gz commit 417ef863ffd9868d086ad1f3046769e7c0dce821 Author: Michael Olson <mwolson@gnu.org> Date: Thu Jan 5 01:46:00 2006 +0000 emms-player-mpd: Quote file argument so that filenames with spaces are treated correctly. darcs-hash:20060105014642-1bfb2-d3de3b0693aa45aa354888143fe038124f3f08d5.gz commit d55a9c702e617e9808213c07847d5a0b803df1c2 Author: forcer <forcer> Date: Wed Jan 4 15:42:00 2006 +0000 Move `emms-cancel-timer' to a compatibility section in emms.el darcs-hash:20060104154238-2189f-946812c2493356d70391bac43323ae75958631ad.gz commit 725f0bd17945de99f325040a8d8cf6abc0206dde Author: Michael Olson <mwolson@gnu.org> Date: Wed Jan 4 22:49:00 2006 +0000 emms-playing-time: Make sure that we don't start more than one timer instance. darcs-hash:20060104224902-1bfb2-46604a22db0c34bd3fd5c9bf8b3d4cf6581361f0.gz commit 976d1266c71cf33ae0fa51b799e85b0465d58db2 Author: Michael Olson <mwolson@gnu.org> Date: Wed Jan 4 22:47:00 2006 +0000 emms-player-mpd: Make it the default to sync the MusicPD playlist with the EMMS playlist, since this is what most EMMS users will probably want. darcs-hash:20060104224734-1bfb2-36155ee21122b7db68b1c1a2ab3adef713ca523c.gz commit 4bc3739cc8fa888a9708285f50196f2f574b0201 Author: Michael Olson <mwolson@gnu.org> Date: Wed Jan 4 08:13:00 2006 +0000 Make emms-player-mpd work with emms-playing-time. darcs-hash:20060104081359-1bfb2-a0a8fad9d64ef84432c8698285f9c8293425152d.gz commit b64ef4cef7b58b20a952d78638125efd21a185ac Author: Michael Olson <mwolson@gnu.org> Date: Wed Jan 4 07:52:00 2006 +0000 emms-player-mpd: Bring this up-to-par with the other backends, in that it can update the current playlist position and load the contents of the current playlist into MusicPD. darcs-hash:20060104075237-1bfb2-09f9e463614cb8a2f067b16a7d197463e96c7718.gz commit 7fe71e6381915e775deed571f7b5c0babdf0f394 Author: Michael Olson <mwolson@gnu.org> Date: Wed Jan 4 06:10:00 2006 +0000 Use timers in a way that is compatible with both Emacs and XEmacs. darcs-hash:20060104061024-1bfb2-a35972f84a96c27a9a4bee6a245a8cbe2d6a8dd1.gz commit 76389c6781d42947ce36fa8b260391935532a941 Author: Michael Olson <mwolson@gnu.org> Date: Tue Jan 3 04:04:00 2006 +0000 emms-player-mpd: Docfix, wait 200 millisecs for process to start, add more output when verbose mode is enabled. darcs-hash:20060103040456-1bfb2-1c56881762563b193eee69dfbf1d4b0f033b962c.gz commit 18153aafcfee4135aefe846072dffe737a299d6f Author: Michael Olson <mwolson@gnu.org> Date: Mon Jan 2 09:07:00 2006 +0000 emms-player-mpd: Fix documentation. The mpc binary is no longer needed. darcs-hash:20060102090752-1bfb2-17b7fe577741369d893c2cb04437be3cbd4d9cdf.gz commit 2a0db7acb0c740a9cfa673ab096c316b9ac9e3d5 Author: Michael Olson <mwolson@gnu.org> Date: Sun Jan 1 02:09:00 2006 +0000 emms-player-mpd: Make sure the process gets closed autommatically when exiting Emacs. darcs-hash:20060101020942-1bfb2-315f558879b5e1989e8c82476b0342edf9142f8c.gz commit 400cae8b98eb32273a9f6a248309e583056fd1bd Author: Michael Olson <mwolson@gnu.org> Date: Sat Dec 31 08:32:00 2005 +0000 Significantly improve (and speed up) MusicPD support. darcs-hash:20051231083223-1bfb2-424c2ad1bc366455e51204f02c69887bc38658f5.gz commit 6f5d5aec27e89f6215b7bcccd4bbefd6d0bb9190 Author: william.xwl <william.xwl> Date: Fri Dec 16 09:19:00 2005 +0000 `emms-score-set-playing' is not really "set", but "add". Fix this. Same for `emms-score-set-file-on-line'. darcs-hash:20051216091938-e8fe6-cbba6bc91a39e46d1585654e51beb590efed1350.gz commit fe75d2aac6312c97b4463b7bf86e459b25228dc4 Author: william.xwl <william.xwl> Date: Tue Dec 13 13:15:00 2005 +0000 Added `emms-playlist-sort-by-score'. darcs-hash:20051213131558-e8fe6-ee2bc9a6c1d608ede136b8ee814a56a2f21ccb55.gz commit 63d50898c2520d529231e0eda708d75c84d9ca78 Author: william.xwl <william.xwl> Date: Tue Dec 13 13:11:00 2005 +0000 Fixed emms-score.el to accommordate with changes in EMMS2. I've also reorganized the code structure a little bit and added bunches of new user interface functions. darcs-hash:20051213131157-e8fe6-0ee9d94670ddd2c5989c970b5c1d77fc5804c758.gz commit f034a2674495dfefa93dd84c80936f25d6f1487a Author: william.xwl <william.xwl> Date: Mon Dec 12 09:47:00 2005 +0000 Move `emms-lyrics-mode' to the end, or it won't work on CVS Emacs. darcs-hash:20051212094752-e8fe6-05d5ecabfe7c14d47b63ff98e969f565975f55a7.gz commit 909f28d8fda2c467be867a3a3942d4bb72ed516a Author: yonirabkin <yonirabkin> Date: Sat Dec 3 19:47:00 2005 +0000 fix mode-alter bug darcs-hash:20051203194736-be80e-90831954d25cd6d0608343e5be7317c8bc467683.gz commit 8f9741378df9aadcb27151f05a84ffe9c7895088 Author: yonirabkin <yonirabkin> Date: Tue Dec 20 12:25:00 2005 +0000 update manual for playlist-mode darcs-hash:20051220122514-be80e-1b89102419c4855ddc84198773351fadc1c722a2.gz commit 0987c5a3e0524c37653455965b8bf86d68940b39 Author: yonirabkin <yonirabkin> Date: Sat Dec 24 10:57:00 2005 +0000 make emms-playlist-mode emacs21.4 compatible darcs-hash:20051224105738-be80e-6312a9a6858f8bf4f101176f2e4b9b5e9b6f3950.gz commit b3480e653238bc759294fed0c429789ea422eb62 Author: yonirabkin <yonirabkin> Date: Sun Dec 18 10:22:00 2005 +0000 fix emms-playlist-save-as-m3u darcs-hash:20051218102218-be80e-70018be27db6320656602308f19cfb502a516ae9.gz commit d6dd7526befbbfd49c15cd14ff1f14938b908bf8 Author: yonirabkin <yonirabkin> Date: Fri Dec 9 16:34:00 2005 +0000 killing and yanking in the interactive playlist buffer darcs-hash:20051209163432-be80e-eb60a5e8cb71fe56aa3ef9f09513a84f3c7a57ac.gz commit 41e4e89f944c12bc9187da62d7ec65f22b4fe232 Author: yonirabkin <yonirabkin> Date: Mon Dec 5 09:20:00 2005 +0000 Killing and yanking darcs-hash:20051205092044-be80e-106a5ba397a5cbc621e12180f3332695629944da.gz commit 5773f6565cc179593020af642e75465cfbfbc42e Author: yonirabkin <yonirabkin> Date: Sun Nov 27 08:56:00 2005 +0000 fix manual sectioning darcs-hash:20051127085636-be80e-51967ab6da702cc6bba6c1d53eaa16f8828f9eb6.gz commit baf748f1c895767a356f4b7053495cf3e9da4a93 Author: yonirabkin <yonirabkin> Date: Sun Nov 20 15:46:00 2005 +0000 Fix conflicts in emms-playlist-mode.el darcs-hash:20051120154643-be80e-465da34d3b711e60b8d83f211377b0d6caeb33cf.gz commit 003e929a5d01cba568d1ecbb6df135f79b0f5a94 Author: yonirabkin <yonirabkin> Date: Fri Nov 25 17:54:00 2005 +0000 Fix emms.texinfo for PDF output (thanks twb) darcs-hash:20051125175445-be80e-24251f3641e15cf0d1031635ecadbc1aa5e27030.gz commit 195fad806d580445aae921b5fc6d1bd0a172d8d3 Author: william.xwl <william.xwl> Date: Sat Nov 19 17:14:00 2005 +0000 Added `emms-playlist-mode-go-popup' for popuping emms-playlist as a side window. darcs-hash:20051119171419-e8fe6-576ff2c8fab5c9023ad4a7960d30aa75a27f89c1.gz commit e1dc8e456fb3fa629ab0918509ab850b70c5b8d4 Author: Trent Buck <trentbuck@gmail.com> Date: Sat Nov 19 15:08:00 2005 +0000 emms-info-mp3info.el (emms-info-mp3find-arguments): use info-tracknumber instead of info-tracknum, so as to be consistent with ogginfo. emms-info.el: Update documentation. darcs-hash:20051119150805-8f417-0d2b6db05e53860d657c6c4fe1f7005a6aaffd28.gz commit a56e48ca823adde74c7f84103b5ab22f8de89661 Author: Trent Buck <trentbuck@gmail.com> Date: Fri Oct 28 14:25:00 2005 +0000 emms-source-file.el: add missing third clause to AUTOLOAD calls. darcs-hash:20051028142538-8f417-24f8937ae61e4b99fdf6e0908aca171855f0785e.gz commit b5bd47545ea803d97bd9107fee096f9c064dcd87 Author: Trent Buck <trentbuck@gmail.com> Date: Sat Nov 19 18:39:00 2005 +0000 emms-info-libtag.el: Fix a couple of typos. darcs-hash:20051119183945-8f417-4a85bfd58f00ae44dc404ef6ebc48e91b3261678.gz commit c959a9d8568e5a5fa318ff2a8e8c46b324a44676 Author: Trent Buck <trentbuck@gmail.com> Date: Sat Nov 19 18:15:00 2005 +0000 Implement an emms-info function using the libtag package. darcs-hash:20051119181528-8f417-cccb6d14779011d1e58eac89474282257768e631.gz commit e169a8955ba16794d0a0ee28abd48e6d78720ffc Author: yonirabkin <yonirabkin> Date: Mon Nov 7 03:42:00 2005 +0000 Finished rewriting manual darcs-hash:20051107034232-be80e-2dd881001cb4561318979c1595186510b906dc80.gz commit 9aa9ca1f92704131ed432e2923384f70e315c100 Author: yonirabkin <yonirabkin> Date: Thu Nov 3 17:01:00 2005 +0000 More manual work, but still only 71 percent done darcs-hash:20051103170157-be80e-8d0fe3a6e38b9c6cf511d1caa12ce08d22cd8c00.gz commit 05d34d279a0cc1d3d8ff3a2ac000f997feedd147 Author: lucas <lucas> Date: Thu Nov 3 18:38:00 2005 +0000 Added support for toggling default action in streams darcs-hash:20051103183830-4f952-4eda4ae86bf6c600f8056ecf6ec570e9a2baa1bd.gz commit 57cb82e43e2bd9682b4391be4d60ba93a002afd2 Author: lucas <lucas> Date: Thu Nov 3 18:38:00 2005 +0000 Added a hook for emms-streams darcs-hash:20051103183801-4f952-73e9e94c3aa34773c1e09eb37b0aec4188bd682f.gz commit 72a409fb89cce29c8ee73c27f0d0f9dccdec7cfc Author: Trent Buck <trentbuck@gmail.com> Date: Thu Oct 27 17:27:00 2005 +0000 debian/emms.emacs-install: Leave symlinks in bytecode dir for find-library/function/variable. darcs-hash:20051027172739-8f417-989397150707d7252d25a8c2af2b7c928a045eaf.gz commit a6eb415ef08cfdcc2b893b33bb6b69abfe0f0c32 Author: Trent Buck <trentbuck@gmail.com> Date: Thu Oct 27 15:04:00 2005 +0000 debian/rules: swap binary-indep and binary-arch bodies, since emms is packages as source code. darcs-hash:20051027150418-8f417-67d3d361141c762d7977151a11b448d97c74f911.gz commit ff8d692ce2a1e4df73bf421d63aeb2718535d895 Author: Trent Buck <trentbuck@gmail.com> Date: Thu Oct 27 13:39:00 2005 +0000 Makefile (ChangeLog): Generate ChangeLog from darcs metadata. debian/rules (build-stamp): Have make generate the ChangeLog. (build-arch): Include ChangeLog and debian/changelog in debian package. darcs-hash:20051027133919-8f417-831560dba011ae058eb50dff57e5faba5c6b64a6.gz commit 66b2f900a4472848d02f47877a34a7fd89d3e901 Author: Trent Buck <trentbuck@gmail.com> Date: Sun Oct 23 01:20:00 2005 +0000 Added simple player "playsound". darcs-hash:20051023012053-8f417-73ef9722cbd8307a362eb93a554d87f9759aba9b.gz commit 22d716f2518880b4c1e8140919287eb18d43228d Author: Trent Buck <trentbuck@gmail.com> Date: Mon Sep 12 13:33:00 2005 +0000 Remove TODO from debian/docs. darcs-hash:20050912133353-8f417-96843c7e416e2208b172512f3e29b3179857bd89.gz commit daef12608ac200f0b9a460bcd009b813fdcb93cc Author: Trent Buck <trentbuck@gmail.com> Date: Mon Sep 12 12:57:00 2005 +0000 Don't attempt to dh_installchangelogs ChangeLog in debian/rules. darcs-hash:20050912125754-8f417-917076f0db746db226056de5f46c4cc0ee98cd4b.gz commit f5d80743af6db6bcc803219ae2fab253c2c2a3ed Author: william.xwl <william.xwl> Date: Wed Oct 26 16:14:00 2005 +0000 Add prefix keys support. darcs-hash:20051026161459-e8fe6-d4a7a1426470a58e2f2935e9c2a694e6d32365b5.gz commit 20d864bd4f5bec88ba5e17b8250727676e2d0fd0 Author: yonirabkin <yonirabkin> Date: Mon Oct 17 15:29:00 2005 +0000 manual 71% done darcs-hash:20051017152934-be80e-a0d126a7a8b0aecb000d69ff156ac471527fc935.gz commit 291aba27f8e22bb9e5142dc4655a0dd82cb0d79c Author: yonirabkin <yonirabkin> Date: Sat Oct 15 10:43:00 2005 +0000 fix emms-info-ogginfo laguange darcs-hash:20051015104340-be80e-ca11a2e2b74f0206b0f8345a8d02589b877a2ded.gz commit 32cc9880056ac6f98f78553290b7b673b2850803 Author: yonirabkin <yonirabkin> Date: Thu Oct 13 18:39:00 2005 +0000 manual update (68% done) darcs-hash:20051013183949-be80e-dda309495d59721e1c9f17a331974eb415ff4c0f.gz commit 6987e3f09444c63c98db27616608d1d8a47aa39f Author: yonirabkin <yonirabkin> Date: Sat Oct 15 14:09:00 2005 +0000 emms-metaplaylist fix requested by Lukhas darcs-hash:20051015140904-be80e-2fbfe070170fbaa50857028fab153907547ddf4e.gz commit 4dd6efe6b70606c8640a34439a4106cd42459dda Author: william.xwl <william.xwl> Date: Sun Oct 16 03:32:00 2005 +0000 A minor spell correction. darcs-hash:20051016033227-e8fe6-595e73a6a15a396c765e93f9d4dba68ee9302b42.gz commit 4d68d4503dbb4638b8562dd552bbbf452b1ecda9 Author: lucas <lucas> Date: Sun Oct 9 13:03:00 2005 +0000 Make emms-mode-line-icon use the good function to get the current track darcs-hash:20051009130300-4f952-86bbf7d1d6c618c68f6de3e84fc452b983b6a22f.gz commit 5fb496d95c75c87604b6d7577bad4c13eb445744 Author: forcer <forcer> Date: Sat Oct 8 07:18:00 2005 +0000 Rename `emms-playlist-save-active-as-m3u' to `emms-playlist-save-current-as-m3u'. darcs-hash:20051008071829-2189f-46167437fb97e67f1b8b6279a5ab5700003b8469.gz commit 8bef0fd0d611ad91b4eb9e5cacc42d7567ff8747 Author: william.xwl <william.xwl> Date: Fri Oct 7 08:47:00 2005 +0000 emms-playlist-sort.el: New file containing various playlist sort functions. darcs-hash:20051007084756-e8fe6-cc88b1e1d581e801dc339ec97a6f5534599d79cf.gz commit ed2e57232a6933e3665557991da261b413dd9dc9 Author: william.xwl <william.xwl> Date: Fri Oct 7 08:46:00 2005 +0000 emms-setup.el: Added `emms-playlist-sort' to `emms-devel'. darcs-hash:20051007084601-e8fe6-90b4a2455d71a02a5cd6d2606e87939e340ff239.gz commit 53b5cbdb8959f143f8e4620b57019f7abd17f825 Author: william.xwl <william.xwl> Date: Thu Oct 6 02:51:00 2005 +0000 emms-setup.el: Moved `emms-lyrics' and `emms-playing-time' into `emms-all'. darcs-hash:20051006025155-e8fe6-6a18f855565ff59f5e4948d4d99a90f981a117bf.gz commit 50a4eb28bb4183731b7fae4edac1cece8f4ccba3 Author: william.xwl <william.xwl> Date: Wed Oct 5 06:49:00 2005 +0000 emms-lyrics.el: New function: `emms-lyrics-restore-mode-line'. darcs-hash:20051005064914-e8fe6-a3bf4ebc649177b6c8774510fc8746c2fa1fa028.gz commit 47c874cbc0e9582c19d56fa2176bd2a473148765 Author: william.xwl <william.xwl> Date: Wed Oct 5 06:48:00 2005 +0000 emms-playing-time.el: New function: `emms-playing-time-restore-mode-line'. darcs-hash:20051005064846-e8fe6-c4f072868018fe19587c9d264de1d1b4057f85e0.gz commit bba3062997c45ff28186c56e6973651c3a21aa07 Author: yonirabkin <yonirabkin> Date: Wed Oct 5 19:13:00 2005 +0000 manual work (57% done) darcs-hash:20051005191315-be80e-030f1f1257759e8d1228a0816d0b99807fe2c861.gz commit 4a5b03f31983d0419dd189c3f2220f17e491bf63 Author: william.xwl <william.xwl> Date: Wed Oct 5 05:53:00 2005 +0000 emms.el: Should initialize `emms-player-paused-p' to nil at start. Or a pause + stop would make `emms-player-paused-p' be wrong. darcs-hash:20051005055332-e8fe6-27c08bc14b67b708d92dc257186a1034e2420286.gz commit c3312693608064f399eea3e4fba5fc45834bf0be Author: william.xwl <william.xwl> Date: Wed Oct 5 05:37:00 2005 +0000 emms-mode-line.el: Made `emms-mode-line-alter' be compatible with `emms-track-updated-functions'. darcs-hash:20051005053723-e8fe6-af820eb0ae971b9f47fd829ad3db9fdc2af5384d.gz commit 6e0e5a6961e8d0454664e832d69dabf3a9917549 Author: william.xwl <william.xwl> Date: Tue Oct 4 16:21:00 2005 +0000 emms-mode-line.el: When artist or title info cann't be achieved, show file name without directory. darcs-hash:20051004162138-e8fe6-dbbeb40bb623c61ac9a1051afcd8c12e4dc11553.gz commit 414b92ad08b4399575f7b0adc6dfa7ee68494322 Author: william.xwl <william.xwl> Date: Tue Oct 4 15:46:00 2005 +0000 emms-mode-line: Changed dead `emms-playlist-current-track-changed-hook' to `emms-track-updated-functions'. darcs-hash:20051004154656-e8fe6-9872e4246c7635987fa79f7a499134b622e3e453.gz commit 3cd3a11cc7d754f34711144c51392548915928a7 Author: yonirabkin <yonirabkin> Date: Tue Oct 4 19:30:00 2005 +0000 emms-playlist-mode-switch-buffer darcs-hash:20051004193020-be80e-d83b29d6a6fd07b0884a9876685ce650229cbaf7.gz commit 5917c93f567e70cfcb6122fc140f603557207788 Author: yonirabkin <yonirabkin> Date: Tue Oct 4 13:49:00 2005 +0000 Yet Another Installment of the manual re-write darcs-hash:20051004134932-be80e-4b875ae487827f1507f8f7dd0f13a37023894976.gz commit c1fc8a4356b804f028858579f99e993d492c9926 Author: yonirabkin <yonirabkin> Date: Sat Oct 1 10:09:00 2005 +0000 emms-setup.el re-write darcs-hash:20051001100929-be80e-4d00edea104b2d18be8f552812550dd547628d44.gz commit 3463b8d83256684a65853d4202f347b40f2fdcba Author: yonirabkin <yonirabkin> Date: Fri Sep 30 21:24:00 2005 +0000 more manual re-writing darcs-hash:20050930212451-be80e-f339987613f6eb5668f180268b1a32d080ac654b.gz commit fff50f931cd9d2682834b16b34939e84e350dafb Author: yonirabkin <yonirabkin> Date: Thu Sep 29 20:52:00 2005 +0000 manual work darcs-hash:20050929205222-be80e-df5516a7c609262ca7a0ed4ffc16a39569a6331f.gz commit fa298a5f4c8a79197c69658c267915bfd9ad946d Author: yonirabkin <yonirabkin> Date: Wed Sep 28 07:13:00 2005 +0000 Another installment of manual changes darcs-hash:20050928071321-be80e-d6ffd8ab5ab0ab84074951d1c869903d2f096dcb.gz commit 7e658c50e8f8a56a06ce6df3cc41bf4cc31a93f2 Author: yonirabkin <yonirabkin> Date: Mon Sep 26 17:24:00 2005 +0000 some manual fixes (just the start) darcs-hash:20050926172449-be80e-2992507a21d9cc719d233f41a5ffd2d1010bb6e3.gz commit a6d3a6d26e449d5c8682477c03118c9193512f7f Author: forcer <forcer> Date: Wed Sep 28 03:42:00 2005 +0000 Rename emms-default.el to emms-setup.el. darcs-hash:20050928034207-2189f-b2873193aedf955414761a1d22c4873f8c7451e6.gz commit a239073e80f4137b0eb95d37d60ed1e047710604 Author: yonirabkin <yonirabkin> Date: Sat Sep 24 13:20:00 2005 +0000 List all the changes needed in the manual darcs-hash:20050924132001-be80e-c3c7da63419c535eb652dec5a74bcce88570e32b.gz commit c6f371b13e0d9f50079d06f106aab704840db016 Author: forcer <forcer> Date: Mon Sep 26 01:28:00 2005 +0000 Update tracks with a specific function, and provide emms-track-updated-functions darcs-hash:20050926012813-2189f-88b12a9350389bba0f12b3d3525b8eb14f066a37.gz commit 7b5a900a765d928153125ad9bb5b164f1de4f6eb Author: Michael Olson <mwolson@gnu.org> Date: Sun Sep 25 16:53:00 2005 +0000 emms.el (emms-playlist-new): Use interactive-p rather than called-interactively-p, since the latter is not available in Emacs21. darcs-hash:20050925165342-1bfb2-f28192eb2f5ce62ad80d94eb760731a83060c43d.gz commit aaf97fcbd6f52b0e2a36726fe8e1f6e1eff78bb4 Author: Michael Olson <mwolson@gnu.org> Date: Sun Sep 25 16:03:00 2005 +0000 emms-streams.el: Update `emms-info-file-info-song-artist' so that it can deal with the new interface. darcs-hash:20050925160336-1bfb2-95abcbab9f4d62c6d8dee2b7a8b3b8523e4089a4.gz commit 5bab7a72a1a5ffc0134fa370b096925fd91c771f Author: Michael Olson <mwolson@gnu.org> Date: Sat Sep 24 18:38:00 2005 +0000 emms-playlist-mode.el: 3rd attempt to not clobber emms-playlist-buffer-p. darcs-hash:20050924183844-1bfb2-7a7c3f5a022a3f877411ac6bc179401dd5aba9d0.gz commit 7c95eebcdd4c731400825d968f5001642eb4999f Author: yonirabkin <yonirabkin> Date: Fri Sep 23 16:43:00 2005 +0000 rollback patch to fix adding tracks. darcs-hash:20050923164324-be80e-fa8a734a8c540dc79482cf7f9634059b236d42dd.gz commit 244fb3fa97e40c6a16885a109b660af093693d22 Author: yonirabkin <yonirabkin> Date: Fri Sep 23 21:30:00 2005 +0000 Adding emms-info-ogginfo.el and consiquently modifying emms-default darcs-hash:20050923213008-be80e-471fff42070a012a822fdd34958b2c65c974a10e.gz commit 66d6f60c1a4fa48d83ee33f1c5c9e4293f72d181 Author: yonirabkin <yonirabkin> Date: Fri Sep 23 17:03:00 2005 +0000 add emms-metaplaylist-mode.el darcs-hash:20050923170348-be80e-1a580b48fcd338db45ef2f069554cc0b946285bb.gz commit 4b8643e5c5d5ad393a3fc538177fa31f37ceed5c Author: william.xwl <william.xwl> Date: Fri Sep 23 16:34:00 2005 +0000 emms-playing-time.el: 1 New functions: `emms-playing-time-enable', `emms-playing-time-disable', `emms-playing-time-toggle', for handling hook stuffs. 2 Removed `emms-playing-time-display-p' where unnecessary now. 3 Updated commentary and author name. :-) darcs-hash:20050923163428-e8fe6-f9871c6d81c9dd347d7d3f1a90c7ccc53052a8f8.gz commit beaeab32a109098ab7c7bf78243177a6162e9ce5 Author: william.xwl <william.xwl> Date: Fri Sep 23 16:32:00 2005 +0000 eemms-lyrics.el: 1 New functions: `emms-lyrics-enable', `emms-lyrics-disable', `emms-lyrics-toggle', for handling hook stuffs. 2 Removed `emms-lyrics-display-p' where unnecessary now. 3 Updated commentary and author name. :-) darcs-hash:20050923163220-e8fe6-b700a37e3388a1dd1051b9e6fa5b79822bac8982.gz commit 78c58f36be38a353407b78cd57503873ca0d7c63 Author: william.xwl <william.xwl> Date: Fri Sep 23 04:23:00 2005 +0000 emms-lyrics.el: Fixed a bug in `emms-lyrics-start'. darcs-hash:20050923042355-e8fe6-f8963a566f39a7ce381c38e6849088215c640d98.gz commit 2a3e1237f2f9c647535f53f8cc798507ed4db0e9 Author: william.xwl <william.xwl> Date: Fri Sep 23 04:22:00 2005 +0000 emms-playing-time.el: Applied standard customization definitions. darcs-hash:20050923042230-e8fe6-7aa526aeb68fa6b3bd964dd17cc5d5627c2c6719.gz commit b2ac5e98453572ab46f717804bdf79aab84286ee Author: forcer <forcer> Date: Thu Sep 22 18:46:00 2005 +0000 emms-info-mp3info: Provide a way to configure the mp3info output coding system. darcs-hash:20050922184657-2189f-122182bd8d0dbb1f966161be07d1c03b121591b1.gz commit caf31401b5ed00a16b1b201204e030f15579b610 Author: forcer <forcer> Date: Thu Sep 22 18:32:00 2005 +0000 Add documentation of the define symbols for emms-info.el. darcs-hash:20050922183214-2189f-97de1c0477b7a8162b6b6f170484eb0b92ddfa4d.gz commit d1075eefa063bd98d165b6ed551d9fc96998be2d Author: yonirabkin <yonirabkin> Date: Thu Sep 22 16:58:00 2005 +0000 remove emms-metaplaylist-mode code from emms-playlist-mode darcs-hash:20050922165801-be80e-ca5535f624ce98446b706f6dc3d183e18b1b1b2c.gz commit 297b183bfafd53b72539fe57aaf88cb32acdb4d5 Author: william.xwl <william.xwl> Date: Thu Sep 22 16:15:00 2005 +0000 emms-playing-time: Since 'info-playing-time is an int now, changed `emms-playing-time-display' accordingly. darcs-hash:20050922161519-e8fe6-10afec9d862e9706358a9d7da3f9041c6d5a8236.gz commit 06aa86fe5f5edc7664442c53bf994362c1bfee21 Author: forcer <forcer> Date: Thu Sep 22 14:54:00 2005 +0000 emms-info-mp3info: Use number for 'info-playing-time. darcs-hash:20050922145403-2189f-3c7ec02551f2a965d18ca2350878c14694037c50.gz commit cd4d94affea79510389155df0ca486e3822b6c04 Author: william.xwl <william.xwl> Date: Thu Sep 22 13:13:00 2005 +0000 emms-playing-time.el: Updated the playing-time retrieval method, so as to be able to display playing-time again. darcs-hash:20050922131319-e8fe6-31a021162b338fa900f3f04916b3232ba75c6efe.gz commit 79e95d09f9aa7467252f06af52f2455d0575c20d Author: Michael Olson <mwolson@gnu.org> Date: Thu Sep 22 13:28:00 2005 +0000 emms-playlist-mode: Make sure emms-playlist-buffer-p is set, since we destroy all local variables. darcs-hash:20050922132808-1bfb2-ac762ce18c460a052e82725eeb9fdf5afe2ff280.gz commit 4214b958e378284769aa321328d05349e8624e4c Author: Michael Olson <mwolson@gnu.org> Date: Thu Sep 22 13:24:00 2005 +0000 emms-playlist-mode-go: Add buffer-live-p check to circumvent a "selecting deleted buffer" error. darcs-hash:20050922132424-1bfb2-69edb479fbda82e7c3e8e9cb9500611844a43b3e.gz commit 50c2d32db87d015e74117cd246bc8708b58dff41 Author: forcer <forcer> Date: Wed Sep 21 16:52:00 2005 +0000 emms-player-mplayer.el: Set resume method to nil to just use pause. darcs-hash:20050921165253-2189f-16a549a2a3ee19c6904d49c4358b94e6a4f36bc8.gz commit ec90d94d50cdfb49d5474190365b71cd6f6267ae Author: yonirabkin <yonirabkin> Date: Wed Sep 21 15:10:00 2005 +0000 fix emms-score.el and emms-info-ogg.el borkage darcs-hash:20050921151000-be80e-f0f52d81156347ffd2469b1cc3fc0f019a1cd597.gz commit cd1f64f873331c5a12fcd0146b0edd6ebfe0b2d9 Author: yonirabkin <yonirabkin> Date: Tue Sep 20 20:13:00 2005 +0000 clean-up emms-info-ogg.el darcs-hash:20050920201300-be80e-1917b1e46f73bc57908ea1236ddf5efb4bf06fcf.gz commit 707ea4c592771085eab2d063c2be0b447503831c Author: yonirabkin <yonirabkin> Date: Tue Sep 20 19:22:00 2005 +0000 fix ogg-info darcs-hash:20050920192219-be80e-5622dc6e2700bf5189f1c985544803b35dbcb26b.gz commit 8b3fe1b890cb5c0ac3581ead85abc45866a0d170 Author: forcer <forcer> Date: Tue Sep 20 20:02:00 2005 +0000 emms-info-mp3info ignores files which are not mp3s darcs-hash:20050920200258-2189f-b022eaf859e07f2433128cb2469eeb935bf12785.gz commit 210dae37326f6e57d2038d746e785840614ee70f Author: forcer <forcer> Date: Tue Sep 20 19:51:00 2005 +0000 Don't set values mp3info has nothing for darcs-hash:20050920195119-2189f-fcfa87d4801c108a5e438c5606f1cda798c50296.gz commit 21ac80ab5f61689eaffff3316dfbbafe4ecde636 Author: forcer <forcer> Date: Tue Sep 20 19:26:00 2005 +0000 later-do.el: Run timer after function did run to avoid stacking darcs-hash:20050920192602-2189f-1edaca802ff8727f0ef077ca99217aa6b6a2f174.gz commit 6aef5b432ee8d76469b1b0e9df22d726836560dd Author: forcer <forcer> Date: Tue Sep 20 19:25:00 2005 +0000 Inefficiency removed: Update each track only once :P darcs-hash:20050920192531-2189f-97973969ed90c9c72be6f4a9951c6de52a4558dc.gz commit fa77f2c443f817f06bc7f0840b8c72de499bd10e Author: forcer <forcer> Date: Tue Sep 20 18:57:00 2005 +0000 Ignore read-onliness when updating a track in a playlist buffer darcs-hash:20050920185705-2189f-fdbbe3e722c0ea46c44d0e7a3c173618ff00ca46.gz commit 4419434e68690130ed655c3aa82d93573f17c151 Author: forcer <forcer> Date: Tue Sep 20 18:56:00 2005 +0000 Use time-less-p instead of <= for times darcs-hash:20050920185652-2189f-09a62b400c47786fabb8ca41ad1476dc780b51d5.gz commit 90af28d88467cbf4d06e6e15eabdd6ce6ca06bad Author: forcer <forcer> Date: Tue Sep 20 18:39:00 2005 +0000 later-do.el emms version darcs-hash:20050920183948-2189f-a3ff550a612f60b402a9090d658b84ee512375e4.gz commit 056631ed63c86bd5c0be5bcb2fe4f538647352ea Author: forcer <forcer> Date: Tue Sep 20 18:29:00 2005 +0000 emms-streams shouldn't overwrite `emms-track-initialize-functions' darcs-hash:20050920182952-2189f-e0f98b3622b5df0fe9a508097e4704a75b0352db.gz commit f2b67055ed55c869b7636b9be7a83a2dfe5dde1c Author: forcer <forcer> Date: Tue Sep 20 18:10:00 2005 +0000 Typo fix (findo -> find) darcs-hash:20050920181036-2189f-af195e1556a42ce36c258c50f3a458fd52aadd02.gz commit 7678cf90a7e74f78a0651b07085aca5de2650a68 Author: forcer <forcer> Date: Tue Sep 20 17:52:00 2005 +0000 emms-info-track-description: Fall back to old behavior if no title and artist darcs-hash:20050920175244-2189f-b1e1413fde30472f7b6d974c7c4a2119f6523dd5.gz commit 9ed18917952044ca8d98812c7c5e3b12cc82041c Author: forcer <forcer> Date: Tue Sep 20 17:13:00 2005 +0000 Hotfix for emms-streams due to info changed. Please fix later. darcs-hash:20050920171329-2189f-4d4df14baa03e0a200039510958b5b782098f4d1.gz commit 0d415cf8ef9ffe5d2bde8b1192a030a6ec193734 Author: forcer <forcer> Date: Tue Sep 20 17:08:00 2005 +0000 Fix emms-default.el, and ignore ogg stuff for now. darcs-hash:20050920170859-2189f-c2774cf5acda1ad25356881025b661e6c679266f.gz commit 827a436a05fec4cca5764e8f06979f024d58775a Author: forcer <forcer> Date: Tue Sep 20 17:02:00 2005 +0000 Remove emms-info-later-do.el darcs-hash:20050920170253-2189f-fe351e79d4c8d4ffd79305916a83c2d2620bd272.gz commit eac49fb242c0e11475b10a74fbaeda1c10fa8ed8 Author: forcer <forcer> Date: Tue Sep 20 17:02:00 2005 +0000 Fix emms-default.el for new emms-info.el darcs-hash:20050920170238-2189f-7e23af6e66de25385c0d2b0466d900990368273a.gz commit d7e4c9c9465fefe3aae7da19f6eac079b06c6670 Author: forcer <forcer> Date: Tue Sep 20 16:59:00 2005 +0000 emms-info-mp3info.el updated for newest emms-info.el darcs-hash:20050920165928-2189f-592a72839b3d1567866d6b7dd40a7c41a20d435e.gz commit 7a0a6df204101c34330cdef60f9b2cb4112729ee Author: forcer <forcer> Date: Tue Sep 20 16:32:00 2005 +0000 emms-info.el rewrite. darcs-hash:20050920163255-2189f-225b911f090628ebe65a51a66927116b7065e8b6.gz commit d6361e597150746437cf1d4fce6db113cf90aabe Author: forcer <forcer> Date: Tue Sep 20 16:01:00 2005 +0000 later-do: Work even if the called function errors out. darcs-hash:20050920160128-2189f-8674b2d67de3428a3a7ab47b36a24342552089e1.gz commit 8da8ace462c9a23d9d8dcde1f18e9a8eae6c1023 Author: forcer <forcer> Date: Tue Sep 20 15:06:00 2005 +0000 emms-random: Use `emms-playlist-current-select-random'. darcs-hash:20050920150644-2189f-a968b0f1a76d015c6939bf0483c78d3d4e1aae30.gz commit 82bd4e9840db47910ed42534a775184026640399 Author: yonirabkin <yonirabkin> Date: Mon Sep 19 21:05:00 2005 +0000 fixing track killing some more darcs-hash:20050919210533-be80e-c5fa4f158225ee65e1b9d65171dcffef02fd0a7c.gz commit 851aa9c3c8d0960076074531d98de5b65ea5725d Author: yonirabkin <yonirabkin> Date: Mon Sep 19 20:38:00 2005 +0000 use insert function for yanking darcs-hash:20050919203816-be80e-c17eaabd2c75f163ee334e2590714b8dc715f457.gz commit 305ef4c196b68dbb0f6e0d9c5f2aa6e4c6670b34 Author: forcer <forcer> Date: Mon Sep 19 16:46:00 2005 +0000 Fixed saving/loading for emms-playlist-mode, also added track updating darcs-hash:20050919164624-2189f-e924677b89b8516dfa409bf23b02643df4c7abe8.gz commit 143785652eb7d6770b1495585da2206f45bbab38 Author: forcer <forcer> Date: Mon Sep 19 16:45:00 2005 +0000 Added track updating to emms. darcs-hash:20050919164537-2189f-e7142b3e3d7b5fabb773ddd54adfc451c6bd6f05.gz commit 3cc364fc552d48e644e48648635a1cba8ad49da0 Author: yonirabkin <yonirabkin> Date: Mon Sep 19 16:02:00 2005 +0000 Added emms-playlist-mode-insert-function (fixed sorting and shuffling font-lock) darcs-hash:20050919160239-be80e-2d58597fe1bc610e96305febbf54365555ae04a1.gz commit 8ff0169a2e17104d9dd3e7e0b826fb8fbdedaa35 Author: yonirabkin <yonirabkin> Date: Mon Sep 19 13:00:00 2005 +0000 Fix bugs in lyrics and mode-line modes when switching songs, fix yanking in playlist buffer darcs-hash:20050919130007-be80e-6b215d9ffeedd6c2a1b90412345560e9718f6d20.gz commit 5a9d752d58773ad9d85ee32c4d9569f73a2cf55c Author: yonirabkin <yonirabkin> Date: Mon Sep 19 12:45:00 2005 +0000 UNDO: Fix track switching error and interactive playlist yanking darcs-hash:20050919124513-be80e-19b15bf7f3d48d50eead0ba1cad39f3f29c89ca3.gz commit 705ef3e86e6cde8e728906784df405c1385c1449 Author: yonirabkin <yonirabkin> Date: Mon Sep 19 12:45:00 2005 +0000 Fix track switching error and interactive playlist yanking darcs-hash:20050919124513-be80e-845e8aa410d52df3c7eb49a87cd08e42c2d55558.gz commit b16b48c14a2126d123925cb4529952bcf1c950a9 Author: yonirabkin <yonirabkin> Date: Mon Sep 19 06:37:00 2005 +0000 Added 'emms-playlist-clear to the default key-map for emms-playlist-mode darcs-hash:20050919063744-be80e-8a48cc617350af06ee126d5e1862d467f87c52bf.gz commit dc3401cab4539e59313affe4e3e7a3596eb43413 Author: mwolson <mwolson> Date: Mon Sep 19 13:53:00 2005 +0000 Make emms-playlist-current-clear an interactive function. darcs-hash:20050919135301-66c01-bb3595657d5e510ad3c22668bcc891a09574da20.gz commit 8406c54c6fbf440c5567027828ab477c972f9752 Author: yonirabkin <yonirabkin> Date: Mon Sep 19 06:54:00 2005 +0000 Added 'emms-playlist-clear to default playlist keymap darcs-hash:20050919065400-be80e-51626c44004d73797f6bb2713da03c36b67e8c2f.gz commit 88486511d43b6eb82d33332cdb9de4e1572b590d Author: yonirabkin <yonirabkin> Date: Sun Sep 18 19:39:00 2005 +0000 include streaming into emms-default and fix streaming info from within the *EMMS Streams* buffer darcs-hash:20050918193906-be80e-b8b8921427703df27d9053bb07b6bcbcf451bd1a.gz commit 75cd35b85f82de1295b4a99a1d117c9774189aa3 Author: mwolson <mwolson> Date: Sun Sep 18 20:03:00 2005 +0000 Make `emms-playlist-clear' interactive so that I can map it to a key. darcs-hash:20050918200341-66c01-bea6b2f0b6930728212be35ce6714faa74cc902d.gz commit 2030e9b1274a92066428ef150f847d9fc24520a5 Author: forcer <forcer> Date: Sun Sep 18 19:44:00 2005 +0000 Make `with-current-emms-playlist' disable read-onlyness. darcs-hash:20050918194432-2189f-a9a8d3e0d34ff56250308a1d812d4d9e110218de.gz commit 6a2419934fd491a24ab91c14feadbbe1522fe690 Author: yonirabkin <yonirabkin> Date: Sun Sep 18 18:53:00 2005 +0000 fix emms-streams.el and emms-player-mplayer.el darcs-hash:20050918185351-be80e-6b9fdd384b25c68e2e1935bd39324c0fc7fe2900.gz commit 5b613ee4d76d6964d0747135271c0875f7c4d3a4 Author: yonirabkin <yonirabkin> Date: Sun Sep 18 18:06:00 2005 +0000 comment out emms-info-playlist breakage darcs-hash:20050918180623-be80e-74f66cbc862e694acae8ec78ca52d1861ca775d1.gz commit a6ffe948ddbb1c061114bdf5b4a7c424d756bc97 Author: forcer <forcer> Date: Sun Sep 18 15:47:00 2005 +0000 emms-playlist-set-playlist-buffer: Ensure the selected buffer is a playlist. darcs-hash:20050918154758-2189f-720bc6d736b60db1d420c97a59eef0c5847fa859.gz commit fcf800bdfa668461ffc4003b73b884632b1c5e78 Author: forcer <forcer> Date: Sun Sep 18 15:38:00 2005 +0000 Ignore read-onliness when opening a playlist-mode-buffer. darcs-hash:20050918153818-2189f-741632f4e0094043b2a9b4a3b4795bbed4114582.gz commit 660a39312ab1506e5e11efec6af6e8f23892239e Author: yonirabkin <yonirabkin> Date: Sun Sep 18 14:37:00 2005 +0000 fixing errors after breakage darcs-hash:20050918143712-be80e-a610dbf62d72b902d4a2d55f598dcc42c652f3aa.gz commit d0efdf999ea41be893b19228b6d0e1c72b9d00d1 Author: forcer <forcer> Date: Sun Sep 18 13:48:00 2005 +0000 Big renaming for current buffer/current playlist distinction. All playlist functions which work on the current playlist now are named `emms-playlist-current-...'. Other functions named `emms-playlist-...' work on the current buffer. This affects the following functions: emms-playlist-clear => emms-playlist-current-clear emms-playlist-selected-track => emms-playlist-current-selected-track emms-playlist-select-next => emms-playlist-current-select-next emms-playlist-select-previous => emms-playlist-current-select-previous emms-playlist-select-random => emms-playlist-current-select-random emms-playlist-select-first => emms-playlist-current-select-first emms-playlist-select-last => emms-playlist-current-select-last emms-playlist-insert-source => emms-playlist-current-insert-source darcs-hash:20050918134805-2189f-2f7c0f1b4828e5438f15906b7a15959b28c97760.gz commit 90cc6addbe21ee379366536fc5ece6cf942fb63a Author: forcer <forcer> Date: Sun Sep 18 13:17:00 2005 +0000 emms-playlist-new: No, it's a major mode, DONT pass an argument! darcs-hash:20050918131728-2189f-c88a72052b9fdc8f1dc63203a2b8e479120d8d0f.gz commit 24d8b5142333d50e6dfc4d908fffb06cd5bfd7b1 Author: lucas <lucas> Date: Sun Sep 18 12:51:00 2005 +0000 Making emms-default now emms-playlist-mode compatible darcs-hash:20050918125105-4f952-230ff24b0e2c179270762b82c0c18db144d4c1dd.gz commit 549de334b204dbc9ba96277a0c46c9a40468c12c Author: forcer <forcer> Date: Sun Sep 18 12:51:00 2005 +0000 emms-playlist-new: Pass positive argument to mode function. darcs-hash:20050918125107-2189f-c2a970ba946ecada105e3de47b90edbb25732711.gz commit 998245fb2e6f025dc4307ff9ebb6f4a195ee17e1 Author: lucas <lucas> Date: Sun Sep 18 12:30:00 2005 +0000 Renaming the "playlist" source to "streamlist". Things might be broken. darcs-hash:20050918123045-4f952-54c6f999429e0e9204c4407f29dc13c5729fa023.gz commit 1c038156cd13b5d0ce3bac875d8782803ab903f6 Author: yonirabkin <yonirabkin> Date: Sun Sep 18 11:13:00 2005 +0000 clean-up pseudo font-locking darcs-hash:20050918111356-be80e-b110448449043fdb7cc75d858c64ef314a7d52ee.gz commit da660a77c5a379b7453bba9ea277ef8cb6bc4f6e Author: yonirabkin <yonirabkin> Date: Sun Sep 18 11:06:00 2005 +0000 "font-locking" for inserted, unselected tracks darcs-hash:20050918110651-be80e-86d1642303a821e4b0bf665124a82ff79f4b9043.gz commit d30e5fe8d8bb874013b1dbdbbc9822b405738429 Author: yonirabkin <yonirabkin> Date: Sun Sep 18 10:22:00 2005 +0000 emms.el missing quote fix, emms-playlist-mode.el kill-track fix darcs-hash:20050918102240-be80e-01feafe2aeab07d9a6f61dcd10027b22abe17812.gz commit 5ea605bdb7972862bbd9df1e7679d64a854eafa0 Author: lucas <lucas> Date: Sun Sep 18 00:21:00 2005 +0000 Adding a bunch of FIXME tags for the playlist source When we come to a consensus on the naming, we'll just fix it. Yrk should have a word about it, stream-playlist sounds good. darcs-hash:20050918002119-4f952-24dbcb9f6fd5e897f7f4879160480f4d6c316740.gz commit f0805a50fc393a89ae73c013ebb532c342c5fc28 Author: lucas <lucas> Date: Sun Sep 18 00:06:00 2005 +0000 Fixing emms-playlist-mode-open-buffer darcs-hash:20050918000605-4f952-6867d44d87365efb09189c1641c8ab1114ebd74d.gz commit 82aa0e5fe261e9205392edf65422b4ada0cead1c Author: forcer <forcer> Date: Sat Sep 17 23:49:00 2005 +0000 emms-playlist-select should not switch to the playlist buffer. darcs-hash:20050917234943-2189f-af7835eb6a888554adbb38ebff4e5bc0c9169c2d.gz commit b442a6a3ab4de2258ceb2625a08a8e87931bb765 Author: lucas <lucas> Date: Sat Sep 17 23:02:00 2005 +0000 Renaming emms-playlist-save to emms-playlist-mode-save-buffer darcs-hash:20050917230231-4f952-9f90c8db115e93b2a4f0baf24b6d2b2a85bcf75d.gz commit ca184383ea5f0628aebd0165da3ba4dd53c7aba3 Author: yonirabkin <yonirabkin> Date: Sat Sep 17 18:43:00 2005 +0000 Added docstrings and clean-up for emms-playlist-mode.el darcs-hash:20050917184331-be80e-625e5442d3579163cf54cd0e1880fdbd0e578739.gz commit 96573c9344c4e5ee89310026c8a7ac92d639a9e1 Author: yonirabkin <yonirabkin> Date: Sat Sep 17 17:28:00 2005 +0000 A kinder, gentler emms-playlist-mode-go darcs-hash:20050917172815-be80e-b12d00404dfa78d5d6647a1b19678a204d7199f4.gz commit b1f7743701939aab80caa3112060c515c30dc387 Author: yonirabkin <yonirabkin> Date: Sat Sep 17 11:53:00 2005 +0000 clean-up and emms-playlist-mode-center-current darcs-hash:20050917115359-be80e-6795d7ec60ac1d8d4fbae659b244044bd4475a75.gz commit 82a67e810ab0037f3ec4cf9e4b4825c9b924b752 Author: william.xwl <william.xwl> Date: Thu Sep 15 15:45:00 2005 +0000 emms-player-mplayer.el: mplayer also knows rm, rmvb, mp4, ...etc. darcs-hash:20050915154517-e8fe6-d999e20df6848f0bdd935636926d41cb166525a0.gz commit deb7e2a2cb02bb0e785ea2fbf7b6a64fc1259deb Author: yonirabkin <yonirabkin> Date: Sat Sep 17 11:33:00 2005 +0000 multiple fixes to emms-playlist-mode.el darcs-hash:20050917113312-be80e-8fe0e28da37075b86053c7f9214f1bb5b44d715e.gz commit 259a95a880d5245e02bd37d9e992f07a59e9e683 Author: forcer <forcer> Date: Sat Sep 17 11:33:00 2005 +0000 emms-show now knows when nothing is playing. darcs-hash:20050917113301-2189f-0d126507e1d0cc0f9fdc7a8d22a9848a27814e29.gz commit 27c872628c0e7899af04e6d369b45d393e7ed69e Author: forcer <forcer> Date: Sat Sep 17 11:14:00 2005 +0000 Inhibit read-only in `emms-playlist-insert-track' darcs-hash:20050917111449-2189f-de933b63402b796f6c2de9a85492c7d2bb4491ad.gz commit 1d93684d37b6adda2be568a1c640534553a270e9 Author: Michael Olson <mwolson@gnu.org> Date: Sat Sep 17 02:11:00 2005 +0000 mpd-updates emms-player-mpd.el: Add handler for 'resume. (emms-player-mpd-paused-p): Remove, since we already have emms-player-paused-p. (emms-player-mpd-pause): Use toggle instead of either play or pause. darcs-hash:20050917021138-1bfb2-733cf6b6af61426e3232ffa36aaa5a7df168a37b.gz commit 4bc68e51697b62d0d740d1062ee1802491c37ca8 Author: lucas <lucas> Date: Fri Sep 16 21:28:00 2005 +0000 Making emms-playlist-mode-go respect emms-playlist-buffer darcs-hash:20050916212845-4f952-74de68c92079fab8aa468bedbcd781d835078691.gz commit 74ffb1b03be6669294921c2e6e754b8f6fc2b2c9 Author: forcer <forcer> Date: Fri Sep 16 21:26:00 2005 +0000 Add `emms-ensure-player-playing-p' darcs-hash:20050916212623-2189f-bda20f8b211ef0ef2e85316c0d9b684fb391b237.gz commit 46f2edc42166eb1a4a840485f410823b9e0c8b72 Author: lucas <lucas> Date: Fri Sep 16 21:21:00 2005 +0000 Adding emms-playlist-mode-save and -open darcs-hash:20050916212134-4f952-f9c41d8ba7a07b8525e8d627e1d5630def0de19c.gz commit 3e97e2a386e287dc5b7acf37a87aa1b8daaa0af8 Author: yonirabkin <yonirabkin> Date: Fri Sep 16 20:22:00 2005 +0000 Small fixes darcs-hash:20050916202237-be80e-e15fcf8f430dd620041567040d8e746d5d83118a.gz commit ddc5477ea066880b471c7c5705429fa99d952efc Author: forcer <forcer> Date: Fri Sep 16 13:53:00 2005 +0000 Be able to clear the playlist buffer even if it's killed. darcs-hash:20050916135349-2189f-7586b026b430eea1471581360b0b5ae8e4a94614.gz commit 9a310175d0c7f6af4088ba8a0425b97a40cc41b0 Author: lucas <lucas> Date: Fri Sep 16 11:39:00 2005 +0000 Adding emms-playlist-save-active-as-m3u darcs-hash:20050916113946-4f952-51f4f9f76f02bb36c32e9979cad37b4ab391f6f2.gz commit 1690b1313085fecc75755498fd4bb59ed9edcadb Author: lucas <lucas> Date: Fri Sep 16 11:39:00 2005 +0000 Fixing a typo in emms-playlist-save-active darcs-hash:20050916113911-4f952-3aba93912d958f141fe139e53dd32c3d83fccad5.gz commit 7d607a99baa1d182e331275be19155369b973bdc Author: lucas <lucas> Date: Fri Sep 16 11:38:00 2005 +0000 Docstrings for playlist saving functions darcs-hash:20050916113805-4f952-0326d97c34e0ebdbbc06dd8223705f6abd3bdb32.gz commit bfc1d52754fea6bffa1ee8e549ecc074199264e1 Author: lucas <lucas> Date: Fri Sep 16 11:35:00 2005 +0000 Adding m3u playlist format for saving. darcs-hash:20050916113519-4f952-6b64bce74a914de5f6ccb336174e6a3fcb877da3.gz commit f47307dd053f8457e7cad556cbc2933881427bbd Author: forcer <forcer> Date: Fri Sep 16 13:40:00 2005 +0000 Added emms-playlist-mode.el darcs-hash:20050916134001-2189f-4dc12e4e9c599b50784cc115a07da94675e8c990.gz commit 829d2f10fbde315aee63e187067f03a80a8ed5a4 Author: forcer <forcer> Date: Fri Sep 16 12:51:00 2005 +0000 Shuffle, sort and source-add don't move point anymore. darcs-hash:20050916125153-2189f-11149468188ec76cafabb03f51edf7870824f07f.gz commit 09a83a3d852966666ff7cfea8737f456ffd751dd Author: forcer <forcer> Date: Fri Sep 16 01:12:00 2005 +0000 Provide source insertion darcs-hash:20050916011202-2189f-8e2e487b296e5a4d69f48c4bf6e19ba54a2274fe.gz commit e028af54dcfc56f04bdabdf6aeba3037e4246fac Author: forcer <forcer> Date: Fri Sep 16 00:51:00 2005 +0000 Cleaned up `emms-playlist-save' a bit darcs-hash:20050916005103-2189f-5ca71f755760a832d2351c221fa58ec500fe1f5e.gz commit 3b340f3c204e9cec0a69d10f6d22297ee6db1038 Author: lucas <lucas> Date: Fri Sep 16 00:42:00 2005 +0000 Adding emms-playlist-save and -active-save Opening will come soon. darcs-hash:20050916004252-4f952-6ddd886a8bb95591ecdb5bd801cafadca0d9ad64.gz commit e7854c9b8b16ee118b5c7aca640f482a339d1cec Author: forcer <forcer> Date: Fri Sep 16 00:33:00 2005 +0000 Fix emms-playlist-new and make emms-playlist-clear use it. darcs-hash:20050916003331-2189f-e450098f69ebd1acf9605479ea9f760fd17d3caf.gz commit 079e9b43cb95ff95649a06e8949e35fdef5a7647 Author: lucas <lucas> Date: Thu Sep 15 22:36:00 2005 +0000 Removing the old emms-save-playlist darcs-hash:20050915223636-4f952-c412dd199396faaac1a400124393c4a08ecf111c.gz commit d5ee498a1c0d2fa545cc8165750d24b454af54d4 Author: forcer <forcer> Date: Thu Sep 15 19:50:00 2005 +0000 emms-source-add now checks for an as of yet unset marker, too. darcs-hash:20050915195059-2189f-47156a6a913df1012caf07bc2b4b68309354334a.gz commit f797263d20955756cef4047d71b9232ed3df6bdc Author: forcer <forcer> Date: Thu Sep 15 19:26:00 2005 +0000 Add `emms-playlist-buffer-p'. darcs-hash:20050915192621-2189f-77ac4024f5f200c66441c741adb7fd7fb16f7aee.gz commit afa65e1b447c45d587cda694b5fa8fa460be4a0f Author: william.xwl <william.xwl> Date: Thu Sep 15 04:15:00 2005 +0000 emms-lyrics.el: Changed to `emms-player-seeked-hook' to `emms-player-seeked-functions', defined in `emms.el'. darcs-hash:20050915041558-e8fe6-2db36d29657d506de085ab8e11b27ad766d3a3e7.gz commit c470a6b67622c7d69d8ae554dee54004b38971a9 Author: william.xwl <william.xwl> Date: Thu Sep 15 04:12:00 2005 +0000 emms-playing-time.el: Changed to `emms-player-seeked-hook' to `emms-player-seeked-functions', defined in `emms.el'. darcs-hash:20050915041250-e8fe6-9158bd4cdc7b6de802ca387dcec5760d20cdf9e3.gz commit 9cdc66aaca76e8fb378f5ba8aaf8a9b2bfd5b419 Author: william.xwl <william.xwl> Date: Thu Sep 15 04:07:00 2005 +0000 emms.el: Fix seek bug in `emms-player-seek'. darcs-hash:20050915040717-e8fe6-cc67bc754b6121308a9de83ebcd1ca55fc53c4d9.gz commit 58f84a976bad80a81c3cf1a2b91fb2b686269931 Author: william.xwl <william.xwl> Date: Wed Sep 14 14:58:00 2005 +0000 emms-lyrics.el: Updated commentary and applied standard customization definitions. darcs-hash:20050914145818-e8fe6-a05a813a3e17ad962d1c3600140895155dbe28d2.gz commit ea1212c32b170340cd2158545bc98bb3d74e7112 Author: forcer <forcer> Date: Wed Sep 14 21:56:00 2005 +0000 ogg-comment.el: Define macros before using them. darcs-hash:20050914215657-2189f-6138e4593adb14f5ae2553b3819510ae03e2cd3c.gz commit f3e2073b312f954940d9fab944525b23f22fc926 Author: forcer <forcer> Date: Wed Sep 14 14:19:00 2005 +0000 Add more mikmod command line args. darcs-hash:20050914141914-2189f-4e29867532782c1fc17100c521c1b1746fb51b73.gz commit 459295382c80cba3327883cd643a8bb1a1144b7d Author: forcer <forcer> Date: Wed Sep 14 14:13:00 2005 +0000 Added mikmod support (thanks to Martin Schoenmakers) darcs-hash:20050914141335-2189f-29e4513d371dbbf7a241e2232c7d24987340546f.gz commit 66df3dd061c024b1e72de5f0d03587f109ffc1a9 Author: forcer <forcer> Date: Wed Sep 14 12:40:00 2005 +0000 emms-playlist-new, emms-playlist-set-playlist-buffer: New commands. darcs-hash:20050914124043-2189f-596b94d21d7715a023d574e9bb97efe001f0a266.gz commit 935c96b110747ea774d6e9a8ddb8d4d73e93b58e Author: forcer <forcer> Date: Wed Sep 14 11:19:00 2005 +0000 Add `emms-player-simple-regexp'. Also, use it as appropriate. darcs-hash:20050914111945-2189f-41013fda35fa58bb063cd33673607d86cd15f3b5.gz commit 427771f9061d95ce1394b63afcf2e3eb592d59d9 Author: lucas <lucas> Date: Wed Sep 14 11:03:00 2005 +0000 Fixing typo in file regexps for gstreamer darcs-hash:20050914110346-4f952-e9342ae8080ee0302dca7f45e4eb3d5ed6a3b34a.gz commit eca575ece92fc749c9d9ed161d1708684125db92 Author: forcer <forcer> Date: Tue Sep 13 23:26:00 2005 +0000 Updated define-emms-simple-player examples in emms.texinfo darcs-hash:20050913232630-2189f-30904f1ec02344bfcc24ddf83735b5e3675d2f9a.gz commit 757479e76a2a6c15554055d10c87a11ca7b51e2a Author: forcer <forcer> Date: Tue Sep 13 14:46:00 2005 +0000 Call widen in shuffle and sort. darcs-hash:20050913144610-2189f-177ce9e62c59598fa2e96d1060df6bac490f3ded.gz commit 24a3b107f48617d130d156b903983a6087a8131a Author: forcer <forcer> Date: Tue Sep 13 14:43:00 2005 +0000 Added `emms-playlist-delete-track-function'. darcs-hash:20050913144350-2189f-a2006aeec64fec759f735934c7c301e1337844cd.gz commit f4e10b6195e40fd413ed6c2eeb4cd333e2ce30fe Author: forcer <forcer> Date: Tue Sep 13 14:41:00 2005 +0000 Remove emms-playlist-kill-track. darcs-hash:20050913144138-2189f-8d561ded2bc4a42cec012ce31353a26535a82327.gz commit f8c762c9cbb8780376408afb3cf403bb61c2b2cf Author: forcer <forcer> Date: Tue Sep 13 14:36:00 2005 +0000 Fix shuffling in combined sources. darcs-hash:20050913143654-2189f-7e3f05cef7eb5160bd1eeab31eaa74878ad991a1.gz commit 4d1b90bc599aa8fe8e3f2bcdbb0cc523e3e3f384 Author: forcer <forcer> Date: Tue Sep 13 13:22:00 2005 +0000 Call `emms-shuffle' to shuffle a source. darcs-hash:20050913132230-2189f-d9d1d3a0969ddf940df4e27051e48303d5033a51.gz commit 4b3b2888b66888ac0ac2352b23f650e23a86e2a0 Author: forcer <forcer> Date: Tue Sep 13 12:22:00 2005 +0000 Cleanup of the shuffle/sort stuff darcs-hash:20050913122202-2189f-9aa7ef59932a59f0f9bd82e958584527dadcda43.gz commit b287337c453a019c686139a1b2a5aebf9a2d760d Author: forcer <forcer> Date: Tue Sep 13 12:03:00 2005 +0000 emms-shuffle-all: Depend on the value of current, not of emms-player-playing-p darcs-hash:20050913120303-2189f-c735a8476728feac9349915a512e9de7356adb01.gz commit 183d1e623555d579cd981e3a32cce0f2f8323643 Author: forcer <forcer> Date: Tue Sep 13 11:56:00 2005 +0000 Don't make emms-playlist-sort and emms-playlist-shuffle interactive. darcs-hash:20050913115644-2189f-26baa0c5e9ad16fdcf21266ea5ac7debfafb1e54.gz commit 2eb4f321a46888dad9fb35996e5d081db1a71517 Author: forcer <forcer> Date: Tue Sep 13 02:06:00 2005 +0000 Keep the selected song correct for shuffling and sorting darcs-hash:20050913020638-2189f-293bdbd2dd6e836d9348adac36e4f67b2a5c751b.gz commit b4c652a8f64b5d1426c47ea216f37ad6ad1861f1 Author: forcer <forcer> Date: Tue Sep 13 01:37:00 2005 +0000 Throw errors for `emms-next' and `emms-previous' at the end/beginning of the playlist darcs-hash:20050913013733-2189f-8af35462c962d2f187a6453ffdc6afbf3d538d70.gz commit c94c41fd6b9618e4a6422266f9e712753a8c199c Author: forcer <forcer> Date: Mon Sep 12 23:36:00 2005 +0000 Added `emms-random[_\c3_]' (idea by twb) darcs-hash:20050912233602-2189f-15c33eafc9d4c587065046a26762fa07359aee0d.gz commit b75e294ed74af4e6a893af7400604e9967f493eb Author: forcer <forcer> Date: Mon Sep 12 23:23:00 2005 +0000 Add shuffling and sorting. darcs-hash:20050912232329-2189f-537afb6d16d9cefda2a009f3b7e4b910597dfbc0.gz commit 8124eab34627950a72a15a1f279c98cc2aaaccc6 Author: forcer <forcer> Date: Mon Sep 12 23:06:00 2005 +0000 Lots of condition-case fixes. darcs-hash:20050912230657-2189f-75349f8e27c54a20151ec3f52ebcfd97af1c810f.gz commit 4ab7c61701b9eb1bac0d75207fdcf8bbe17dbec2 Author: lucas <lucas> Date: Mon Sep 12 17:23:00 2005 +0000 First attempt at reading playing time for .ogg Problem : it's a bit long to read the info now. We need to optimize that. darcs-hash:20050912172312-4f952-73cffb3445ed251fd8cb7e5d691f7c95a676bda0.gz commit 731479aad60f6d75e3371503b3ccc0c29496dbd6 Author: forcer <forcer> Date: Mon Sep 12 15:22:00 2005 +0000 Move gstreamer support into simple player. darcs-hash:20050912152239-2189f-e1b16eaa105d479db199254efc639d0cbe4d3bb2.gz commit 03055c8e7e2c4bd1a62529af1273bedbf803d7c9 Author: forcer <forcer> Date: Mon Sep 12 15:22:00 2005 +0000 Add pause and resume to the simple player. darcs-hash:20050912152217-2189f-f2dbdea100c53cfe38fa47fc65d235eb1bf80323.gz commit 79dc6ebe7d16b3a85f90e1846bf31c0e4e5629a8 Author: forcer <forcer> Date: Mon Sep 12 15:03:00 2005 +0000 emms-stream-info.el: Use emms-playlist-selected-track. darcs-hash:20050912150302-2189f-87c1942fd76673c2bfcb3e4c06a5a15d03e68e06.gz commit 6b60d175cdd429140b5c35cfb32005a7e2b1a76b Author: lucas <lucas> Date: Mon Sep 12 14:45:00 2005 +0000 Removed old gstreamer wrappers darcs-hash:20050912144558-4f952-9568e78d793e65eab5f1189fbb4c3a613407fbae.gz commit f2b85bfdd6156d2af71d7421c8a017ef76a4c98b Author: lucas <lucas> Date: Mon Sep 12 14:44:00 2005 +0000 Added new generic wrapper for gstreamer darcs-hash:20050912144453-4f952-ab068073ee53136739fa12b05fbe23d0da4170d3.gz commit e9e3f8c582c8d810d1027ba7ad36c0ff5f38e047 Author: lucas <lucas> Date: Mon Sep 12 14:43:00 2005 +0000 Fixed typo in emms.el Non quoted hook variable darcs-hash:20050912144334-4f952-750c40ef21e07114e08bb541b6922d29c65e2628.gz commit f4b96cd517218ec82eb02360216b76f841cd9aae Author: lucas <lucas> Date: Mon Sep 12 14:42:00 2005 +0000 Rewrote emms-player-gstreamer darcs-hash:20050912144233-4f952-041bcf7e8a09c0d53eeb1fd7840c0f3e82995355.gz commit 0994a7c585ff45c60ec140f754859fd295cf5bd4 Author: forcer <forcer> Date: Mon Sep 12 13:52:00 2005 +0000 Typo: It's emms-playlist-insert-track, not ...-track-insert. darcs-hash:20050912135246-2189f-e88b69611f0dc35f654c6e4e8cf6b2d169ca1dea.gz commit 58fd1dff80e3a96b13f693f7eafac5688000e356 Author: forcer <forcer> Date: Mon Sep 12 13:39:00 2005 +0000 emms-player-mpd doesn't need emms-player-extensions anymore. darcs-hash:20050912133923-2189f-72ec43a9f8a8fc4a3d61423db6c887675dec2d0d.gz commit c79c2e3e1ac394fe24082f333282cf9f4bfe613b Author: forcer <forcer> Date: Mon Sep 12 13:08:00 2005 +0000 FAQ: Typo fix (Thes -> The) darcs-hash:20050912130801-2189f-bacda3ce92c62f31414ae7f7b7812a878b554fe7.gz commit 7b1a8d2abfebe09f4ab49095f2b4976bd13cfcd6 Author: lucas <lucas> Date: Mon Sep 12 12:58:00 2005 +0000 Fixing the extensions problem. Just removed the requires, and added require mplayer in emms-default. darcs-hash:20050912125805-4f952-c8233776b898931b835cd6d6674b003ee01572ee.gz commit 699cf4d82a5f96cdfb9f0e0d7b8f3c4da834bc19 Author: forcer <forcer> Date: Mon Sep 12 12:53:00 2005 +0000 Select a track after adding, too, if none is selected. darcs-hash:20050912125342-2189f-e56edb2dfc0bc82f822c05dd4e2d67722b5f4fde.gz commit 58a13760b87d70587eb92cdb415779ad8fd34858 Author: forcer <forcer> Date: Mon Sep 12 12:42:00 2005 +0000 Rename emms-mpd.el to emms-player-mpd.el darcs-hash:20050912124204-2189f-9882f477cd27d74ce9ff8ca39fc82d8169983d7c.gz commit 7d8661b26343424cacf67c6344fcebdcdbab581c Author: forcer <forcer> Date: Mon Sep 12 12:40:00 2005 +0000 Rename emms-lyric.el to emms-lyrics.el darcs-hash:20050912124035-2189f-7c4f6bc6a1f9f8414e3071219ab843b1fa37f5c8.gz commit b628c03d46abc951b79b884a816fcafaa4562f47 Author: forcer <forcer> Date: Mon Sep 12 12:35:00 2005 +0000 Add speex support darcs-hash:20050912123529-2189f-3d86b8d06e5f1425308cf841b1648dcd37ea6228.gz commit 60e841e1dd91d89be4168774c77fdbda2118e469 Author: forcer <forcer> Date: Mon Sep 12 12:31:00 2005 +0000 Add pause and seek support to emms.el. This factors out the mplayer support into emms-player-mplayer.el, and removes emms-player-extensions.el. darcs-hash:20050912123151-2189f-8ead830f8f4e50f883325f308423b6f7677ea8d9.gz commit 2b26cd1027757dca1b34f0479b9ec65c249c923b Author: lucas <lucas> Date: Mon Sep 12 11:56:00 2005 +0000 renaming the provide, Emacs complains otherwise darcs-hash:20050912115634-4f952-1f34052b3767ed2ee2dc5500642bd8ba6ba231b8.gz commit bd397bd12c8832b0a91c7fb224ede7620f683999 Author: lucas <lucas> Date: Mon Sep 12 11:44:00 2005 +0000 Fixed emms-mode-line-icon and -playing-time darcs-hash:20050912114449-4f952-7673b38ea57a6c34a59500c0ae1769a98fb28c9f.gz commit c1308f0e1322af1cc1677b8487271700b2ae91c8 Author: forcer <forcer> Date: Mon Sep 12 11:50:00 2005 +0000 Rename emms-gstreamer.el to emms-player-gstreamer.el darcs-hash:20050912115010-2189f-ca853d135f22c7c55b55f268a87e8e8accaaac26.gz commit 649edac3b50b7eed9a7ca8f4f85a8783a8e84bbc Author: lucas <lucas> Date: Mon Sep 12 11:23:00 2005 +0000 fixing emms-lyric.el and emms-mode-line.el I don't have any lyric file, so I can't test it. But there are no errors :) darcs-hash:20050912112331-4f952-2981436bdf7b89f559c9888bdde58ec5345abadd.gz commit 4f169973a679b402334a9e3ae919d26729f4784e Author: forcer <forcer> Date: Mon Sep 12 10:59:00 2005 +0000 emms.el (with-current-emms-playlist): Also recreate when the buffer is dead. darcs-hash:20050912105908-2189f-9511f1b22cef47e3a6b6aa4ab3ad2bc0ba08c03d.gz commit bc7be1f4d0ea2cf0e67d2b805868df6652f2eeaa Author: forcer <forcer> Date: Sun Sep 11 20:21:00 2005 +0000 emms.el (emms-next-noerror): Always return non-nil when `emms-playlist-select-next' doesn't error out. darcs-hash:20050911202113-2189f-4e933a7bbe447057bdba8ce192ef841d5790fc4d.gz commit 3a573a243b134f7e4244f87cdf53c3538265e15f Author: forcer <forcer> Date: Sun Sep 11 20:05:00 2005 +0000 Playlist buffer rewrite darcs-hash:20050911200536-2189f-fcbbdb6ca90b3e5c3a68162dd5ae841057dac920.gz commit bb65333ef00df02dbf6bd83294b4df49e64ea325 Author: forcer <forcer> Date: Sun Sep 11 20:05:00 2005 +0000 Initial commit (CVS 2005-09-11) darcs-hash:20050911200506-2189f-48a136015e33465c3cf09940ce935ec2203df463.gz ������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������